我有一个用 Java 编写的服务器式软件,可以在 Windows 和 OS X 上运行。(它不是在服务器上运行,而只是在普通用户的 PC 上运行 - 类似于 torrent 客户端。)我希望软件发出信号到操作系统以在机器处于活动状态时保持机器唤醒(防止其进入睡眠模式)。
当然,我不希望有一个跨平台的解决方案,但我希望我的应用程序可以生成一些非常小的 C 程序/脚本,以通知操作系统保持清醒。
有任何想法吗?
我有一个用 Java 编写的服务器式软件,可以在 Windows 和 OS X 上运行。(它不是在服务器上运行,而只是在普通用户的 PC 上运行 - 类似于 torrent 客户端。)我希望软件发出信号到操作系统以在机器处于活动状态时保持机器唤醒(防止其进入睡眠模式)。
当然,我不希望有一个跨平台的解决方案,但我希望我的应用程序可以生成一些非常小的 C 程序/脚本,以通知操作系统保持清醒。
有任何想法吗?
我使用此代码来防止我的工作站被锁定。它目前只设置为每分钟移动一次鼠标,但您可以轻松调整它。
这是一个 hack,而不是一个优雅的解决方案。
import java.awt.*;
import java.util.*;
public class Hal{
public static void main(String[] args) throws Exception{
Robot hal = new Robot();
Random random = new Random();
while(true){
hal.delay(1000 * 60);
int x = random.nextInt() % 640;
int y = random.nextInt() % 480;
hal.mouseMove(x,y);
}
}
}
在 Windows 上,使用SystemParametersInfo函数。这是一种瑞士军队风格的功能,可让您获取/设置各种系统设置。
要禁用屏幕关闭,例如:
SystemParametersInfo( SPI_SETPOWEROFFACTIVE, 0, NULL, 0 );
完成后请务必将其重新设置...
添加到上述 Scarcher2 的代码片段中,并且仅将鼠标移动 1 个像素。我已经移动了两次鼠标,即使指针处于极端状态也会发生一些变化:
while(true){
hal.delay(1000 * 30);
Point pObj = MouseInfo.getPointerInfo().getLocation();
System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y);
hal.mouseMove(pObj.x + 1, pObj.y + 1);
hal.mouseMove(pObj.x - 1, pObj.y - 1);
pObj = MouseInfo.getPointerInfo().getLocation();
System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y);
}
我有一种非常强力的技术,可以将鼠标沿 x 方向移动 1 点,然后每 3 分钟返回一次。
我可能有一个更优雅的解决方案,但它是一个快速修复。
所有来回移动鼠标的建议不会让用户发疯吗?我知道一旦我可以隔离它,我会删除任何会这样做的应用程序。
一个更简洁的解决方案是使用 JNA 来利用本机 OS API。在运行时检查您的平台,如果它恰好是 Windows,那么以下将起作用:
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
import com.sun.jna.platform.win32.WTypes.LPWSTR;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.StdCallLibrary;
/**
* Power management.
*
* @see <a href="https://stackoverflow.com/a/20996135/14731">https://stackoverflow.com/a/20996135/14731</a>
*/
public enum PowerManagement
{
INSTANCE;
@FieldOrder({"version", "flags", "simpleReasonString"})
public static class REASON_CONTEXT extends Structure
{
public static class ByReference extends REASON_CONTEXT implements Structure.ByReference
{
}
public ULONG version;
public DWORD flags;
public LPWSTR simpleReasonString;
}
private interface Kernel32 extends StdCallLibrary
{
HANDLE PowerCreateRequest(REASON_CONTEXT.ByReference context);
/**
* @param powerRequestHandle the handle returned by {@link #PowerCreateRequest(REASON_CONTEXT.ByReference)}
* @param requestType requestType is the ordinal value of {@link PowerRequestType}
* @return true on success
*/
boolean PowerSetRequest(HANDLE powerRequestHandle, int requestType);
/**
* @param powerRequestHandle the handle returned by {@link #PowerCreateRequest(REASON_CONTEXT.ByReference)}
* @param requestType requestType is the ordinal value of {@link PowerRequestType}
* @return true on success
*/
boolean PowerClearRequest(HANDLE powerRequestHandle, int requestType);
enum PowerRequestType
{
PowerRequestDisplayRequired,
PowerRequestSystemRequired,
PowerRequestAwayModeRequired,
PowerRequestMaximum
}
}
private final Kernel32 kernel32;
private HANDLE handle = null;
PowerManagement()
{
// Found in winnt.h
ULONG POWER_REQUEST_CONTEXT_VERSION = new ULONG(0);
DWORD POWER_REQUEST_CONTEXT_SIMPLE_STRING = new DWORD(0x1);
kernel32 = Native.load("kernel32", Kernel32.class);
REASON_CONTEXT.ByReference context = new REASON_CONTEXT.ByReference();
context.version = POWER_REQUEST_CONTEXT_VERSION;
context.flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
context.simpleReasonString = new LPWSTR("Your reason for changing the power setting");
handle = kernel32.PowerCreateRequest(context);
if (handle == WinBase.INVALID_HANDLE_VALUE)
throw new AssertionError(Native.getLastError());
}
/**
* Prevent the computer from going to sleep while the application is running.
*/
public void preventSleep()
{
if (!kernel32.PowerSetRequest(handle, Kernel32.PowerRequestType.PowerRequestSystemRequired.ordinal()))
throw new AssertionError("PowerSetRequest() failed");
}
/**
* Allow the computer to go to sleep.
*/
public void allowSleep()
{
if (!kernel32.PowerClearRequest(handle, Kernel32.PowerRequestType.PowerRequestSystemRequired.ordinal()))
throw new AssertionError("PowerClearRequest() failed");
}
}
然后当用户运行时,powercfg /requests
他们会看到:
SYSTEM:
[PROCESS] \Device\HarddiskVolume1\Users\Gili\.jdks\openjdk-15.0.2\bin\java.exe
Your reason for changing the power setting
你应该能够为 macOS 和 Linux 做类似的事情。
这里是完成生成java代码的批处理文件,编译它,清理生成的文件,并在后台运行..(你的笔记本电脑上需要jdk)
只需将其保存并作为 Bat 文件运行即可。(somefilename.bat) ;)
@echo off
setlocal
rem rem if JAVA is set and run from :startapp labeled section below, else the program exit through :end labeled section.
if not "[%JAVA_HOME%]"=="[]" goto start_app
echo. JAVA_HOME not set. Application will not run!
goto end
:start_app
echo. Using java in %JAVA_HOME%
rem writes below code to Energy.java file.
@echo import java.awt.MouseInfo; > Energy.java
@echo import java.awt.Point; >> Energy.java
@echo import java.awt.Robot; >> Energy.java
@echo //Mouse Movement Simulation >> Energy.java
@echo public class Energy { >> Energy.java
@echo public static void main(String[] args) throws Exception { >> Energy.java
@echo Robot energy = new Robot(); >> Energy.java
@echo while (true) { >> Energy.java
@echo energy.delay(1000 * 60); >> Energy.java
@echo Point pObj = MouseInfo.getPointerInfo().getLocation(); >> Energy.java
@echo Point pObj2 = pObj; >> Energy.java
@echo System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y); >> Energy.java
@echo energy.mouseMove(pObj.x + 10, pObj.y + 10); >> Energy.java
@echo energy.mouseMove(pObj.x - 10, pObj.y - 10); >> Energy.java
@echo energy.mouseMove(pObj2.x, pObj.y); >> Energy.java
@echo pObj = MouseInfo.getPointerInfo().getLocation(); >> Energy.java
@echo System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y); >> Energy.java
@echo } >> Energy.java
@echo } >> Energy.java
@echo } >> Energy.java
rem compile java code.
javac Energy.java
rem run java application in background.
start javaw Energy
echo. Your Secret Energy program is running...
goto end
:end
rem clean if files are created.
pause
del "Energy.class"
del "Energy.java"
一段时间以来,我一直在使用pmset来控制 Mac 上的睡眠模式,而且它很容易集成。这是一个粗略的示例,说明如何从 Java 调用该程序以禁用/启用睡眠模式。请注意,您需要 root 权限才能运行 pmset,因此您需要它们来运行此程序。
import java.io.BufferedInputStream;
import java.io.IOException;
/**
* Disable sleep mode (record current setting beforehand), and re-enable sleep
* mode. Works with Mac OS X using the "pmset" command.
*/
public class SleepSwitch {
private int sleepTime = -1;
public void disableSleep() throws IOException {
if (sleepTime != -1) {
// sleep time is already recorded, assume sleep is disabled
return;
}
// query pmset for the current setting
Process proc = Runtime.getRuntime().exec("pmset -g");
BufferedInputStream is = new BufferedInputStream(proc.getInputStream());
StringBuffer output = new StringBuffer();
int c;
while ((c = is.read()) != -1) {
output.append((char) c);
}
is.close();
// parse the current setting and store the sleep time
String outString = output.toString();
String setting = outString.substring(outString.indexOf(" sleep\t")).trim();
setting = setting.substring(7, setting.indexOf(" ")).trim();
sleepTime = Integer.parseInt(setting);
// set the sleep time to zero (disable sleep)
Runtime.getRuntime().exec("pmset sleep 0");
}
public void enableSleep() throws IOException {
if (sleepTime == -1) {
// sleep time is not recorded, assume sleep is enabled
return;
}
// set the sleep time to the previously stored value
Runtime.getRuntime().exec("pmset sleep " + sleepTime);
// reset the stored sleep time
sleepTime = -1;
}
}
您可以使用程序 Caffeine caffiene让您的工作站保持清醒。您可以通过 os X 中的 open 命令运行该程序。
在 OS X 上,只需 spawn caffeinate
。这将防止系统休眠,直到caffeinate
终止。
在 Visual Studio 中创建一个简单的表单。从工具栏中,将 Timer 控件拖到窗体上。在初始化代码中,将计时器间隔设置为 60 秒(60000 毫秒)。使用以下代码实现计时器回调“SendKeys.Send("{F15}");” 运行新程序。
无需鼠标移动。
编辑:至少在我的陆军工作站上,简单地以编程方式生成鼠标和按键消息不足以让我的工作站保持登录和唤醒。Java Robot 类的早期海报正走在正确的轨道上。JAVA Robot 在操作系统的 HAL(硬件抽象层)之上或之下工作,但是我重新创建并测试了 Java/Robot 解决方案,但它没有工作——直到我在代码中添加了 Robot.keyPress(123)。
禁用服务器上的电源管理不是更容易吗?可能有人认为服务器不应该进入省电模式?
此代码将指针移动到它已经存在的相同位置,因此用户不会注意到任何差异。
while (true) {
Thread.sleep(180000);//this is how long before it moves
Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
Robot rob = new Robot();
rob.mouseMove(mouseLoc.x, mouseLoc.y);
}
要使用用户 Gili 为 Windows 提供的使用 JNA 的解决方案,这里是适用于 MacOS 的 JNA 解决方案。
一、JNA库接口:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.platform.mac.CoreFoundation;
import com.sun.jna.ptr.IntByReference;
public interface ExampleIOKit extends Library {
ExampleIOKit INSTANCE = Native.load("IOKit", ExampleIOKit.class);
CoreFoundation.CFStringRef kIOPMAssertPreventUserIdleSystemSleep = CoreFoundation.CFStringRef.createCFString("PreventUserIdleSystemSleep");
CoreFoundation.CFStringRef kIOPMAssertPreventUserIdleDisplaySleep = CoreFoundation.CFStringRef.createCFString("PreventUserIdleDisplaySleep");
int kIOReturnSuccess = 0;
int kIOPMAssertionLevelOff = 0;
int kIOPMAssertionLevelOn = 255;
int IOPMAssertionCreateWithName(CoreFoundation.CFStringRef assertionType,
int assertionLevel,
CoreFoundation.CFStringRef reasonForActivity,
IntByReference assertionId);
int IOPMAssertionRelease(int assertionId);
}
下面是调用 JNA 方法来打开或关闭睡眠预防的示例:
public class Example {
private static final Logger _log = LoggerFactory.getLogger(Example.class);
private int sleepPreventionAssertionId = 0;
public void updateSleepPrevention(final boolean isEnabled) {
if (isEnabled) {
if (sleepPreventionAssertionId == 0) {
final var assertionIdRef = new IntByReference(0);
final var reason = CoreFoundation.CFStringRef.createCFString(
"Example preventing display sleep");
final int result = ExampleIOKit.INSTANCE.IOPMAssertionCreateWithName(
ExampleIOKit.kIOPMAssertPreventUserIdleDisplaySleep,
ExampleIOKit.kIOPMAssertionLevelOn, reason, assertionIdRef);
if (result == ExampleIOKit.kIOReturnSuccess) {
_log.info("Display sleep prevention enabled");
sleepPreventionAssertionId = assertionIdRef.getValue();
}
else {
_log.error("IOPMAssertionCreateWithName returned {}", result);
}
}
}
else {
if (sleepPreventionAssertionId != 0) {
final int result = ExampleIOKit.INSTANCE.IOPMAssertionRelease(sleepPreventionAssertionId);
if (result == ExampleIOKit.kIOReturnSuccess) {
_log.info("Display sleep prevention disabled");
}
else {
_log.error("IOPMAssertionRelease returned {}", result);
}
sleepPreventionAssertionId = 0;
}
}
}
}
在计时器内运行命令,例如 ping 服务器。
我只是做一个移动鼠标的功能(或下载免费赠品应用程序)。不优雅,但很容易。
这将起作用:
public class Utils {
public static void main(String[] args) throws AWTException {
Robot rob = new Robot();
PointerInfo ptr = null;
while (true) {
rob.delay(4000); // Mouse moves every 4 seconds
ptr = MouseInfo.getPointerInfo();
rob.mouseMove((int) ptr.getLocation().getX() + 1, (int) ptr.getLocation().getY() + 1);
}
}
}
我用来避免“Windows 桌面自动锁定”的一种简单方法是每 6 秒“打开/关闭 NumLock”。
这是一个打开/关闭 NumLock 的 Java 程序。
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class NumLock extends Thread {
public void run() {
try {
boolean flag = true;
do {
flag = !flag;
Thread.sleep(6000);
Toolkit.getDefaultToolkit().setLockingKeyState(KeyEvent. VK_NUM_LOCK, flag);
}
while(true);
}
catch(Exception e) {}
}
public static void main(String[] args) throws Exception {
new NumLock().start();
}
}
在单独的命令提示符下运行这个 Java 程序;:-)