We know how to force shutdown an computer using Java. For example, the following code works fine for force shutdown:
public static void main(String arg[]) throws IOException{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("shutdown -s -t 0");
System.exit(0);
}
Now, suppose if I want to force startup a computer (which is in shut down state), at a particular time, is it possible to do in Java or any other language?
You need something to trigger the startup. The best way to trigger this is Wake On Lan.
If you want to do this in Java, this might be a good resource.
In addition to wake on lan, there are IPMI devices that run on some server-grade hardware that is connected to the motherboard and can control power as well as provide serial console output over a network connection. This computer is running all the time, but I'm not familiar with any you can load your own code onto.
You can control this device remotely to power control the server that is off from any language including java.
http://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface
If your BIOS supports Advanced Power Management (APM) version 1.2 or later, it should be possible to wake it from sleep/standy or hibernation based on a timer. On Windows an end user can do this through Task Scheduler, and if you wish to do it programmatically you can use the Task Scheduler interfaces.
I don't know how you would do this through Java, but here is some example C code that will create a task to wake the computer up 2 minutes in the future:
#include <mstask.h>
#include <time.h>
int main() {
HRESULT hr = CoInitialize(NULL);
if (SUCCEEDED(hr)) {
ITaskScheduler *scheduler;
hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&scheduler);
if (SUCCEEDED(hr)) {
ITask *task;
hr = scheduler->NewWorkItem(L"Wake Timer", CLSID_CTask, IID_ITask, (LPUNKNOWN*)&task);
if (SUCCEEDED(hr)) {
WORD index;
ITaskTrigger *trigger;
hr = task->CreateTrigger(&index, &trigger);
if (SUCCEEDED(hr)) {
time_t t = time(NULL) + 120;
struct tm *ltime = localtime(&t);
TASK_TRIGGER triggertime;
memset(&triggertime, 0, sizeof(triggertime));
triggertime.cbTriggerSize = sizeof(TASK_TRIGGER);
triggertime.wBeginYear = ltime->tm_year+1900;
triggertime.wBeginMonth = ltime->tm_mon+1;
triggertime.wBeginDay = ltime->tm_mday;
triggertime.wStartHour = ltime->tm_hour;
triggertime.wStartMinute = ltime->tm_min;
triggertime.TriggerType = TASK_TIME_TRIGGER_ONCE;
trigger->SetTrigger(&triggertime);
trigger->Release();
}
task->SetFlags(TASK_FLAG_DELETE_WHEN_DONE|TASK_FLAG_SYSTEM_REQUIRED|TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
task->SetAccountInformation(L"", NULL);
IPersistFile *file;
hr = task->QueryInterface(IID_IPersistFile, (void**)&file);
if (SUCCEEDED(hr)) {
file->Save(NULL, TRUE);
file->Release();
}
task->Release();
}
scheduler->Release();
}
CoUninitialize();
}
return 0;
}
Assumedly if you can do this on Windows, there must be equivalent APIs for other operating systems.
I did manage to find a similar question floating around on the internet, so I'll post the links here to see if you find it helpful. (this was the thread I found: http://www.coderanch.com/t/440680/gc/interact-Windows-Task-Scheduler-Java)
First of all though, I might add that Java is a language that must run in a Virtual Machine - there are no two ways around it. I'm not well versed in 'low-level' programming, such as programming at closer to BIOS level, which is sort of where we are heading with this.
As the question was explicitly about Java, the best I could come up with from research, is (if you're really wanting to use Java for something), using the JAVA-COM (JACOB) http://sourceforge.net/projects/jacob-project/ which allows you to hook into the Windows Task Scheduler http://msdn.microsoft.com/en-us/library/aa383581%28VS.85%29.aspx via the COM language (AF
As far as I am aware, because Java needs to be in a virtual machine to run, there would be no way of getting it to do an action such as turning on a PC - let's not even get into issues of whether such an action would require administrator or above privileges.
Hope that helps.
Related
I am extremely new the Android app development and Stack Overflow. I am trying to recreate traceroute in an Android app since Android devices do not come with traceroute by default. I've encountered a couple stack overflow posts talking about solutions to this, but I have still run into challenges.
Traceroute on android - the top post on this thread links an Android Studio project that implements traceroute using ping. If I understand the algorithm correctly, it continually pings the destination IP, incrementing the time-to-live field to obtain information about intermediary routers. I've tried to recreate this behavior, but for certain values of TTL, the ping stalls and doesn't retrieve any router information. I'm not really sure why this happens. Here's a quick demo function I spun up... at some point in the loop the pings stall.
public static void smallTracerouteDemoShowingThatTheProgramStallsAtCertainTTLs() {
try {
String host = "google.com";
int maxTTL = 20;
for (int i = 1; i < maxTTL; i++) {
// Create a process that executes the ping command
Process p = Runtime.getRuntime().exec("ping -c 1 -t " + i + " " + host);
// Get a buffered reader with the information returned by the ping
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
// Convert the BufferedReader to a string
String dataReturnedByPing = "";
for (String line; (line = br.readLine()) != null; dataReturnedByPing += "\n"+line);
// Print out information about each TTL
System.out.println("TTL = " + i + " out of " + maxTTL);
System.out.println(dataReturnedByPing);
System.out.println("========================================");
}
} catch (Exception e) {
e.printStackTrace();
}
}
how to run traceroute command through your application? - The solution on this thread suggests using BusyBox. I've not used BusyBox as yet, but it seems like I would have to embed BusyBox into my app to get things to work. After doing some research it looks like BusyBox provides numerous Linux commands through one executable. I'm a bit hesitant to explore this option because I really only need the traceroute command. In addition, I know that Android targets a few different CPU architectures, and I'm not sure if one executable will support them all.
I've also run into a github repository that takes another approach to running traceroute:
https://github.com/wangjing53406/traceroute-for-android - In this repository the author embeds the traceroute source code into the project and uses the NDK to build the source code along with the rest of his app. I really like this approach because it feels the most "correct." It uses a built traceroute instead of a Java-based implementation, so you can't find yourself in a situation where the Java implementation gives you one thing and the actual traceroute gives you another. When I open this project to experiment with it, my build fails. The top line says:
org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: A problem occurred configuring root project 'traceroute-for-android-master'.
Any help on why this happens or ways to troubleshoot it would be fantastic.
For reference, the minimum SDK I am targeting is API 21 and I am running on Android Studio 3.3.0.
So, at this point I'm stumped. If you were trying to make an app that would let you execute traceroute commands, how would you do it? I really like the NDK approach because it guarantees you're getting true traceroute behavior. If you have any guides to getting that set up for my Android version/SDK, I would appreciate if you would post them. If you'd take another approach I'd to hear about it as well.
Thank you in advance.
I'm trying to get current network speed like shown in System Monitor on GNOME.
I need this to be in terminal and if possible no installations needed (on most of distros this tool i need should be installed by default with the system).
So i don't want to ping anything or stuff like that, I just want to check speed in simplest way possible without adding new tools.
I hope there is a tool that will show information in terminal like System Monitor -> Resources -> Network history.
EDIT:
if there is a workaround in Java to get this information without using linux commands this would be great
It's difficult to know what tools you already have installed on your system. I'd recommend either bmon, ifstat, or ifstat -S if you want the information printed on the same time.
The above should be in your distro's central repository (aptitude, yum etc) so should be easy to install if they're not aready there.
The Java class InetAddress has an isReachable() method. You could try this:
public long getSpeed() {
InetAddress inet = InetAddress.getByName("stackoverflow.com");
long start = System.currentTimeMillis();
boolean reachable = inet.isReachable(5000);
if (reachable) {
long end = System.currentTimeMillis();
return end - start;
} else {
return -1;
}
}
This will 'sort of' do a ping, but how the isReachable() method is implemented is not really specified. Doing an actual ping command from Java itself is not supported though, so this is (I think) the best you can do.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
java/shellscript code to find out if a jar file is already running on current machine
I would love to get a cross-platform solution for this, but even if it's unix only- that would be fine.
The simple solution would be to do this from the shell (Pseudocode)(if ps -aux | grep myJar | print {awk 2}.contains myPID, don't run myProgram.
Now unfortunately our linux team doesn't want a script like that running in production since it can (admittedly) have undesired behaviors.
So what I need is to be able to have a file run, and when it runs see if another program is running. If the program is already running and it's below that time limit, it should prevent the program from running.
A bit of an example:
Myprog.jar -- timeout 5 min
Myprog.jar is in a cron that gets called every 4 minutes,
the first time it's called it launches, the second time it's called it's still running, but since it's not over the timeout, it's fine.
If it's still running when the third check comes through (at 8 minutes into execution) it's killed, and its process is replaced by itself afterwards.
If someone can help me understand how to do this (We've been trying to set up a lock file with limited success)
Thanks!
You could make your program open a dummy file for writing with a FileWriter when your program starts, and keep the file open until the program is finished.
When you now start a second instance of your program, it will also try to open this file for writing, which will throw an IOException, because only one process can have a write handle to a file at the same time.
You could use a port as a semaphore. See this question for more info on that. I think a port would be a good cross-platform solution
You can create a temporary file on a fixed location.
private static final File LOCK_FILE = new File("app.lock");
public static boolean checkIfAlreadyRunning()
{
return LOCK_FILE.exists();
}
public static void createLockFile()
{
LOCK_FILE.createNewFile();
Runnable shutDown = new Runnable()
{
public void run()
{
try
{
LOCK_FILE.delete();
} catch (Exception e) { /* Sad but true */ }
}
};
Runtime.getRuntime().addShutdownHook(new Thread(shutDown));
Thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Exception e)
{
shutDown.run();
System.exit(-1);
}
});
}
I had exactly the same problem, and it can be pretty tricky to solve. Both File and Socket based approaches can be made to work, but it gets really tricky on some OS's (think of Windows with multiple users in multiple terminal server sessions etc.).
First, determine the scope where you want only one instance. Then decide on a solution.
The ServerSocket method with a fixed port number will allow you one instance per machine (maybe not exactly what you want).
The locking file approach can be tailored to create the locking file in the users temp directoy, so it gives one instance per session/user.
I personally use a combined approach where the locking file specifies a random port and a second instance connects to that port to pass command line parameter to the running instance.
I want to be able to do something like that:
Process p = getRunningProcess(pid)
If there's a way, does it matter how the process was created (using java, using python, from the shell, etc...)?
It is possible to attach to another JVM process from Java app (e.g. to be able to monitor what's going on and potentially detect problems before they happen). You can do this by using the Attach API. Don't know much about attaching to non-JVM processes.
String name = ...
List vms = VirtualMachine.list();
for (VirtualMachineDescriptor vmd: vms) {
if (vmd.displayName().equals(name)) {
VirtualMachine vm = VirtualMachine.attach(vmd.id());
String agent = ...
vm.loadAgent(agent);
// ...
}
}
Yes there is a way to attach any non-JVM process with ProcessHandle.
Here a code Example that starts the calculator and closes it by using the pid.
Process calc = Runtime.getRuntime().exec("gnome-calculator");
Thread.sleep(2000);
long pid = calc.pid();
Optional<ProcessHandle> optionalProcessHandle = ProcessHandle.of(pid);
optionalProcessHandle.ifPresent(ProcessHandle::destroy);
But make sure to run Java SE/JDK 11 or higher and to import java.util.Optional;.
See the documentation to see further methods that can be used with ProcessHandle:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ProcessHandle.html
Credits to java.lang.ProcessHandle - compilation error for being a template for this.
I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of javaw.exe:
NativeLibrary lib;
try {
lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
Logger.out.error("Could not load Shell32 library.");
return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
Function function = lib.getFunction(functionName);
int ret = function.invokeInt(args);
if (ret != 0) {
Logger.out.error(function.getName() + " returned error code "
+ ret + ".");
}
} catch (UnsatisfiedLinkError e) {
Logger.out.error(functionName + " was not found in "
+ lib.getFile().getName() + ".");
// Function not supported
}
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
Working implementation
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.
I don't have Windows 7 but here is something that might get you started:
On the Java side:
package com.stackoverflow.homework;
public class MyApplication
{
static native boolean setAppUserModelID();
static
{
System.loadLibrary("MyApplicationJNI");
setAppUserModelID();
}
}
And on the native side, in the source code of the `MyApplicationJNI.dll library:
JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);
return hr == S_OK;
}
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:
you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.
EDIT: JNA Solution.
References:
The JNI book for more JNI examples
Java Native Access (JNA)
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. Applications using it can be properly pinned to the Windows 7 taskbar. You can also create your own jump lists, etc.
I have implemented access to the SetCurrentProcessExplicitAppUserModelID method using JNA and it works quite well when used as the MSDN documentation suggests. I've never used the JNA api in the way you have in your code snippet. My implementation follows the typical JNA usage instead.
First the Shell32 interface definition:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
Then using JNA to load Shell32 and call the function:
final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );
Many of the API's in the last article you mentioned make use of Windows COM which is quite difficult to use directly with JNA. I have had some success creating a custom DLL to call these API's (eg. using the SHGetPropertyStoreForWindow to set a different app ID for a submodule window) which I then use JNA to access at runtime.
Try to use JSmooth. I use always this one. In JSmooth is there an option under Skeleton by Windowed Wrapper called
Lauch java app in exe process
See on this image.
(source: andrels.com)
Also command line arguments can be passed.
I think this can be a solution for you.
Martijn
SetCurrentProcessExplicitAppUserModelID (or SetAppID()) would in fact do what you're trying to do. However, it might be easier to modify your installer to set the AppUserModel.ID property on your shortcut - quoting from the Application User Model ID document mentioned above:
In the System.AppUserModel.ID property of the application's shortcut file. A shortcut (as an IShellLink, CLSID_ShellLink, or a .lnk file) supports properties through IPropertyStore and other property-setting mechanisms used throughout the Shell. This allows the taskbar to identify the proper shortcut to pin and ensures that windows belonging to the process are appropriately associated with that taskbar button.
Note: The System.AppUserModel.ID property should be applied to a shortcut when that shortcut is created. When using the Microsoft Windows Installer (MSI) to install the application, the MsiShortcutProperty table allows the AppUserModelID to be applied to the shortcut when it is created during installation.
The latest jna-platform library now includes JNA bindings for SetCurrentProcessExplicitAppUserModelID:
https://github.com/java-native-access/jna/pull/680
I fixed mine without any ID settings.
There is an option in Launch4J if you are using it and you say you do then...
You can change the header to JNI Gui and then wrap it around the jar with the JRE.
The good thing is that it runs .exe in the process now instead on running javaw.exe with your jar. It probably does it under the hood (not sure).
Also I have noticed also that it takes around 40-50% less CPU resource which is even better!
And the pinning works fine and all that window features are enabled.
I hope it helps to someone as I spent nearly 2 days trying to solve that issue with my undecorated javafx app.