diff --git a/platform/platform-impl/src/com/intellij/diagnostic/WindowsDefenderChecker.java b/platform/platform-impl/src/com/intellij/diagnostic/WindowsDefenderChecker.java index 01b0fa9ad228..24a85b25e262 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/WindowsDefenderChecker.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/WindowsDefenderChecker.java @@ -21,6 +21,7 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; @@ -74,9 +75,9 @@ public class WindowsDefenderChecker { RealtimeScanningStatus scanningStatus = getRealtimeScanningEnabled(); if (scanningStatus == RealtimeScanningStatus.SCANNING_ENABLED) { final Collection processes = getExcludedProcesses(); - final String binaryName = Restarter.getCurrentProcessExecutableName(); - if (binaryName != null && processes != null && - processes.contains(StringUtil.substringAfterLast(binaryName.toLowerCase(), "\\")) && + final File exe = Restarter.getIdeStarter(); + if (exe != null && processes != null && + processes.contains(exe.getName().toLowerCase(Locale.ENGLISH)) && processes.contains("java.exe")) { return new CheckResult(RealtimeScanningStatus.SCANNING_DISABLED, Collections.emptyMap()); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java index 98fb7bbd9bbc..093d182d32ed 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java @@ -19,12 +19,11 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.updateSettings.impl.ExternalUpdateManager; -import com.intellij.openapi.util.AtomicNullableLazyValue; -import com.intellij.openapi.util.NullableLazyValue; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.AppUIUtil; import com.intellij.util.ExceptionUtil; +import com.intellij.util.Restarter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,26 +42,6 @@ import static com.intellij.util.containers.ContainerUtil.newHashMap; public class CreateDesktopEntryAction extends DumbAwareAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateDesktopEntryAction"); - private static final NullableLazyValue ourScript = new AtomicNullableLazyValue() { - @Nullable - @Override - protected String compute() { - String binPath = PathManager.getBinPath(); - ApplicationNamesInfo names = ApplicationNamesInfo.getInstance(); - - String execPath = binPath + '/' + names.getProductName() + ".sh"; - if (new File(execPath).canExecute()) return execPath; - - execPath = binPath + '/' + StringUtil.toLowerCase(names.getProductName()) + ".sh"; - if (new File(execPath).canExecute()) return execPath; - - execPath = binPath + '/' + names.getScriptName() + ".sh"; - if (new File(execPath).canExecute()) return execPath; - - return null; - } - }; - public static boolean isAvailable() { return SystemInfo.isXWindow && !ExternalUpdateManager.isRoaming() && SystemInfo.hasXdgOpen(); } @@ -140,11 +119,11 @@ public class CreateDesktopEntryAction extends DumbAwareAction { throw new RuntimeException(ApplicationBundle.message("desktop.entry.icon.missing", binPath)); } - String execPath = ourScript.getValue(); - if (execPath == null) { + File starter = Restarter.getIdeStarter(); + if (starter == null) { throw new RuntimeException(ApplicationBundle.message("desktop.entry.script.missing", binPath)); } - execPath = StringUtil.wrapWithDoubleQuote(execPath); + String execPath = StringUtil.wrapWithDoubleQuote(starter.getPath()); ApplicationNamesInfo names = ApplicationNamesInfo.getInstance(); @@ -210,9 +189,4 @@ public class CreateDesktopEntryAction extends DumbAwareAction { return myContentPane; } } - - @Nullable - public static String getLauncherScript() { - return ourScript.getValue(); - } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java index 879a6386d248..c2122e64f7de 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ExceptionUtil; +import com.intellij.util.Restarter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -160,8 +161,8 @@ public class CreateLauncherScriptAction extends DumbAwareAction { } private static File createLauncherScriptFile() throws IOException, ExecutionException { - String runPath = SystemInfo.isMac ? StringUtil.trimEnd(PathManager.getHomePath(), "/Contents") : CreateDesktopEntryAction.getLauncherScript(); - if (runPath == null) throw new IOException(ApplicationBundle.message("desktop.entry.script.missing", PathManager.getBinPath())); + File starter = Restarter.getIdeStarter(); + if (starter == null) throw new IOException(ApplicationBundle.message("desktop.entry.script.missing", PathManager.getBinPath())); ClassLoader loader = CreateLauncherScriptAction.class.getClassLoader(); assert loader != null; @@ -169,7 +170,7 @@ public class CreateLauncherScriptAction extends DumbAwareAction { pair("$PYTHON$", INTERPRETER_NAME.getValue()), pair("$CONFIG_PATH$", PathManager.getConfigPath()), pair("$SYSTEM_PATH$", PathManager.getSystemPath()), - pair("$RUN_PATH$", runPath)); + pair("$RUN_PATH$", starter.getPath())); String launcherContents = StringUtil.convertLineSeparators(ExecUtil.loadTemplate(loader, "launcher.py", variables)); return ExecUtil.createTempExecutableScript("launcher", "", launcherContents); diff --git a/platform/platform-impl/src/com/intellij/util/Restarter.java b/platform/platform-impl/src/com/intellij/util/Restarter.java index 40ef8a3020be..54ef7aa182f1 100644 --- a/platform/platform-impl/src/com/intellij/util/Restarter.java +++ b/platform/platform-impl/src/com/intellij/util/Restarter.java @@ -4,14 +4,16 @@ package com.intellij.util; import com.intellij.execution.configurations.PathEnvironmentVariableUtil; import com.intellij.execution.process.UnixProcessManager; import com.intellij.execution.process.WinProcessManager; -import com.intellij.ide.actions.CreateDesktopEntryAction; import com.intellij.jna.JnaLoader; +import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.updateSettings.impl.UpdateInstaller; import com.intellij.openapi.util.AtomicNotNullLazyValue; import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.NullableLazyValue; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.WString; @@ -19,6 +21,7 @@ import com.sun.jna.platform.win32.WinDef; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.StdCallLibrary; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -47,12 +50,15 @@ public class Restarter { if (!JnaLoader.isLoaded()) { problem = "JNA not loaded"; } + else if (ourStarter.getValue() == null) { + problem = "GetModuleFileName() failed"; + } else { problem = checkRestarter("restarter.exe"); } } else if (SystemInfo.isMac) { - if (getMacOsAppDir() == null) { + if (ourStarter.getValue() == null) { problem = "not a bundle: " + PathManager.getHomePath(); } else { @@ -63,7 +69,7 @@ public class Restarter { if (UnixProcessManager.getCurrentProcessId() <= 0) { problem = "cannot detect process ID"; } - else if (CreateDesktopEntryAction.getLauncherScript() == null) { + else if (ourStarter.getValue() == null) { problem = "cannot find launcher script in " + PathManager.getBinPath(); } else if (PathEnvironmentVariableUtil.findInPath("python") == null && PathEnvironmentVariableUtil.findInPath("python3") == null) { @@ -107,6 +113,38 @@ public class Restarter { } } + public static @Nullable File getIdeStarter() { + return ourStarter.getValue(); + } + + private static final NullableLazyValue ourStarter = new NullableLazyValue() { + @Override + protected File compute() { + if (SystemInfo.isWindows && JnaLoader.isLoaded()) { + Kernel32 kernel32 = Native.load("kernel32", Kernel32.class); + char[] buffer = new char[32767]; // using 32,767 as buffer size to avoid limiting ourselves to MAX_PATH (260) + int result = kernel32.GetModuleFileNameW(null, buffer, new WinDef.DWORD(buffer.length)).intValue(); + if (result != 0) return new File(Native.toString(buffer)); + } + else if (SystemInfo.isMac) { + File appDir = new File(PathManager.getHomePath()).getParentFile(); + if (appDir != null && appDir.getName().endsWith(".app") && appDir.isDirectory()) return appDir; + } + else if (SystemInfo.isUnix) { + String binPath = PathManager.getBinPath(); + ApplicationNamesInfo names = ApplicationNamesInfo.getInstance(); + File starter = new File(binPath, names.getProductName() + ".sh"); + if (starter.canExecute()) return starter; + starter = new File(binPath, StringUtil.toLowerCase(names.getProductName()) + ".sh"); + if (starter.canExecute()) return starter; + starter = new File(binPath, names.getScriptName() + ".sh"); + if (starter.canExecute()) return starter; + } + + return null; + } + }; + private static void restartOnWindows(boolean elevate, String... beforeRestart) throws IOException { Kernel32 kernel32 = Native.load("kernel32", Kernel32.class); Shell32 shell32 = Native.load("shell32", Shell32.class); @@ -118,12 +156,10 @@ public class Restarter { kernel32.LocalFree(argvPtr); // See https://blogs.msdn.microsoft.com/oldnewthing/20060515-07/?p=31203 - // argv[0] as the program name is only a convention, i.e. there is no guarantee - // the name is the full path to the executable. - final String binaryName = getCurrentProcessExecutableName(); - if (binaryName != null) { - argv[0] = binaryName; - } + // argv[0] as the program name is only a convention, i.e. there is no guarantee the name is the full path to the executable + File starter = ourStarter.getValue(); + if (starter == null) throw new IOException("GetModuleFileName() failed"); + argv[0] = starter.getPath(); List args = new ArrayList<>(); args.add(String.valueOf(pid)); @@ -153,20 +189,6 @@ public class Restarter { TimeoutUtil.sleep(500); } - // - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197(v=vs.85).aspx - // To retrieve the full path to the executable, use "GetModuleFileName(NULL, ...)". - // - // Note: We use 32,767 as buffer size to avoid limiting ourselves to MAX_PATH (260). - public static String getCurrentProcessExecutableName() { - Kernel32 kernel32 = Native.load("kernel32", Kernel32.class); - char[] buffer = new char[32767]; - if (kernel32.GetModuleFileNameW(null, buffer, new WinDef.DWORD(buffer.length)).intValue() > 0) { - return Native.toString(buffer); - } - return null; - } - private static String[] getRestartArgv(String[] argv) { String mainClass = System.getProperty("idea.main.class.name", "com.intellij.idea.Main"); @@ -188,7 +210,7 @@ public class Restarter { } private static void restartOnMac(String... beforeRestart) throws IOException { - File appDir = getMacOsAppDir(); + File appDir = ourStarter.getValue(); if (appDir == null) throw new IOException("Application bundle not found: " + PathManager.getHomePath()); List args = new ArrayList<>(); args.add(appDir.getPath()); @@ -196,14 +218,9 @@ public class Restarter { runRestarter(new File(PathManager.getBinPath(), "restarter"), args); } - private static File getMacOsAppDir() { - File appDir = new File(PathManager.getHomePath()).getParentFile(); - return appDir != null && appDir.getName().endsWith(".app") && appDir.isDirectory() ? appDir : null; - } - private static void restartOnUnix(String... beforeRestart) throws IOException { - String launcherScript = CreateDesktopEntryAction.getLauncherScript(); - if (launcherScript == null) throw new IOException("Launcher script not found in " + PathManager.getBinPath()); + File starterScript = ourStarter.getValue(); + if (starterScript == null) throw new IOException("Starter script not found in " + PathManager.getBinPath()); int pid = UnixProcessManager.getCurrentProcessId(); if (pid <= 0) throw new IOException("Invalid process ID: " + pid); @@ -216,14 +233,14 @@ public class Restarter { List args = new ArrayList<>(); if ("python".equals(python.getName())) { args.add(String.valueOf(pid)); - args.add(launcherScript); + args.add(starterScript.getPath()); Collections.addAll(args, beforeRestart); runRestarter(script, args); } else { args.add(script.getPath()); args.add(String.valueOf(pid)); - args.add(launcherScript); + args.add(starterScript.getPath()); Collections.addAll(args, beforeRestart); runRestarter(python, args); }