如何检测应用程序是否从 dmg 文件运行?

cus*_*der 5 macos dmg node.js electron

我们的一些用户似乎从 dmg 文件运行应用程序,并且从未将其移动到他们的/Applications文件夹中:

在此输入图像描述

这可以解释为什么我们在内部日志中看到此消息:

Cannot update while running on a read-only volume. The application is on a read-only volume. Please move the application and try again. If you're on macOS Sierra or later, you'll need to move the application out of the Downloads directory. See https://github.com/Squirrel/Squirrel.Mac/issues/182 for more information.
Run Code Online (Sandbox Code Playgroud)

(我访问了 GitHub 问题,但找不到任何有用的东西。)

我绝对可以通过将 dmg、cd 安装到其中并从命令行运行应用程序来重现此错误消息:

Cannot update while running on a read-only volume. The application is on a read-only volume. Please move the application and try again. If you're on macOS Sierra or later, you'll need to move the application out of the Downloads directory. See https://github.com/Squirrel/Squirrel.Mac/issues/182 for more information.
Run Code Online (Sandbox Code Playgroud)

当应用程序运行时,后台进程会检查更新。我们可以看到它已经找到并下载了它。但它无法应用它。

我们定期发布更新,但这些用户无法获取它们。我怀疑他们中的一些人甚至没有意识到他们没有“正确”安装该应用程序。

有没有一种方法可以用 Electron 或 Node.js 检测到这一点?

cus*_*der 2

这个答案来自我的 Electron 食谱存储库:
https://customcommander.github.io/electron-survival-guide/


TL; DR

您可以使用该app.isInApplicationsFolder()方法。


主要流程

渲染器进程可以Applications通过在in-app-folderIPC 通道中询问来询问应用程序是否正在从该文件夹运行。主进程将在同一通道中响应。

const {app, BrowserWindow, ipcMain} = require('electron');
const path = require('path');

app.whenReady().then(async () => {
  const bwin = new BrowserWindow({
    width: 300,
    height: 300,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.resolve(__dirname, 'preload.js')
    }
  });

  // Must be registered **before** the renderer process starts.
  ipcMain.handle('in-app-folder', () => app.isInApplicationsFolder());

  await bwin.loadFile('renderer.html');
  bwin.show();
});
Run Code Online (Sandbox Code Playgroud)

预加载脚本

预加载脚本在MY_APP命名空间下公开一个方法,渲染器进程可以使用该方法来了解应用程序是否从该文件夹运行Applications

const {contextBridge, ipcRenderer} = require('electron');

contextBridge.exposeInMainWorld('MY_APP', {
  async isInApplicationsFolder() {
    return ipcRenderer.invoke('in-app-folder');
  }
});
Run Code Online (Sandbox Code Playgroud)

渲染器

命名MY_APP空间在预加载脚本中定义,并包含查询应用程序位置的方法。

<html>
  <head>
    <style>
      body {background-color:black;color:limegreen}
    </style>
  </head>
  <body>
    <h1>Are you running this app from the Applications folder?</h1>
    <div id="response"></div>
    <script>
      MY_APP.isInApplicationsFolder().then(yes => {
        if (yes) {
          document.querySelector('#response').innerHTML = 'Yes';
        } else {
          document.querySelector('#response').innerHTML = 'No';
        }
      });
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述