{"id":3659,"date":"2024-03-02T23:44:33","date_gmt":"2024-03-02T14:44:33","guid":{"rendered":"https:\/\/test.ji0vwl.net\/?p=3659"},"modified":"2024-03-18T22:51:49","modified_gmt":"2024-03-18T13:51:49","slug":"mac%e3%81%a8-electron-forge-react-mui-%e3%81%a7pc%e3%82%a2%e3%83%97%e3%83%aa%e3%82%92%e4%bd%9c%e3%82%8b%ef%bc%88%e3%81%9d%e3%81%ae%ef%bc%94%ef%bc%89","status":"publish","type":"post","link":"https:\/\/ji0vwl.net\/index.php\/2024\/03\/02\/3659\/","title":{"rendered":"Mac\u3068 Electron Forge + React + MUI \u3067PC\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\uff08\u305d\u306e\uff14\uff09"},"content":{"rendered":"<p><a href=\"https:\/\/test.ji0vwl.net\/index.php\/2024\/02\/25\/3632\/\">Mac\u3068 Electron Forge + React + MUI \u3067PC\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\uff08\u305d\u306e\uff13\uff09<\/a>\u306e\u7d9a\u304d\u3067\u3059\u3002<\/p>\n<p><a href=\"https:\/\/qiita.com\/uta-member\/items\/0590bb3832cac9fd41ec\">\u3053\u3061\u3089<\/a>\u3092\u53c2\u8003\u306b\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u3001OS\u306e\u4efb\u610fShell\u30b3\u30de\u30f3\u30c9\uff08ls\u3068\u304bdf\u3068\u304b\uff09\u3092\u5b9f\u884c\u3057\u8868\u793a\u3059\u308b\u6a5f\u80fd\u3092\u4f5c\u6210\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u307e\u305a\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u3067\u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u884c\u3059\u308b\u305f\u3081\u306echild_process\u3068\u3044\u3046\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u3001\u30b3\u30de\u30f3\u30c9\u306e\u5b9f\u884c\u6642\u306b\u8fd4\u3063\u3066\u304f\u308b\u6587\u5b57\u306e\u30b3\u30fc\u30c9\u3092ShiftJIS\u304bUnicode\u306b\u5909\u63db\u3059\u308b\u305f\u3081\u306b\u3001encoding-japanese\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3002<\/p>\n<pre>$ npm install child_process encoding-japanese\r\n<\/pre>\n<p>\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u306b\u95a2\u6570\u3092\u4f5c\u308a\u307e\u3059\u3002src\/main\u306bfunctions\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u3057\u3001\u4e2d\u306bShell\u30b3\u30de\u30f3\u30c9\u5b9f\u884c\u6a5f\u80fd shellFunction.ts \u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n<pre>$ cd ~\/electron\/my-app\/src\/main\r\n$ mkdir functions\r\n$ cd functions\r\n<\/pre>\n<pre>$ vim shellFunction.ts\r\n-----\r\nimport {\r\n  ipcMain,\r\n  NotificationConstructorOptions,\r\n  Notification,\r\n} from \"electron\";\r\nimport { promisify } from \"util\";\r\nconst childProcess = require(\"child_process\");\r\nconst Encoding = require(\"encoding-japanese\");\r\n\r\n\/**\r\n * s-jis\u3092Unicode\u306b\u5909\u63db\u3059\u308b\u95a2\u6570\r\n * @param bytes s-jis\u306e\u6587\u5b57\u5217                                                                                        \r\n * @returns\r\n *\/\r\nexport const SJIStoUNICODE = (bytes: string) =&gt; {\r\n  return Encoding.convert(bytes, {\r\n    from: \"SJIS\",\r\n    to: \"UNICODE\",\r\n    type: \"string\",\r\n  });\r\n};\r\n\r\n\/**\r\n * \u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u884c\u3059\u308b\u95a2\u6570\r\n * @param cmd \u5b9f\u884c\u3057\u305f\u3044\u30b3\u30de\u30f3\u30c9\r\n * @returns \u30b3\u30de\u30f3\u30c9\u306e\u5b9f\u884c\u7d50\u679c\r\n *\/\r\nconst cmdFunction = async (cmd: string): Promise&lt;string&gt; =&gt; {\r\n  const exec = promisify(childProcess.exec);\r\n  try {\r\n    const result = await exec(cmd, { encoding: \"Shift_JIS\" });\r\n    if (result?.error) {\r\n      const errorstr = SJIStoUNICODE(result.error);\r\n      return errorstr;\r\n    }\r\n\r\n    const stdout = SJIStoUNICODE(result.stdout);\r\n\r\n    return stdout;\r\n  } catch (err) {\r\n    console.error(err);\r\n    return \"\u30b3\u30de\u30f3\u30c9\u304c\u4e0d\u6b63\u3067\u3059\";\r\n  }\r\n};\r\n\r\nconst shellFunctionListener = () =&gt; {\r\n  \/\/ \u623b\u308a\u5024\u306e\u3042\u308b\u3082\u306e\u306f\"handle\"\u3067\u30ea\u30b9\u30ca\u30fc\u3092\u7acb\u3066\u3066\u3001\r\n  \/\/ \u30ec\u30f3\u30c0\u30e9\u30fc\u5074\u306finvoke\u3092\u4f7f\u3063\u3066\r\n  ipcMain.handle(\r\n    \"exec-cmd\",\r\n    async (event, [cmd]: string[]) =&gt; await cmdFunction(cmd)\r\n  );\r\n};\r\n\r\nexport default shellFunctionListener;\r\n-----\r\n:wq\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>main.ts \u3092\u7de8\u96c6\u3057\u3066\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u4fee\u6b63\u3057\u307e\u3059\u3002mainWindow\u306f\u5916\u306b\u51fa\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<pre>$ cd ..\/\r\n$ vim main.ts\r\n-----\r\nimport { app, BrowserWindow } from 'electron';\r\nimport path from 'path';\r\n<strong>import shellFunctionListener from \".\/functions\/shellFunction\";<\/strong>                                                                   \r\n\r\n\/\/ \u6a5f\u80fd\r\n<strong>shellFunctionListener();<\/strong>\r\n\r\n\/\/ let\u3067\u5ba3\u8a00\u3002\u3082\u3068\u306econst\u306f\u524a\u9664\r\n<strong>let mainWindow: BrowserWindow | null = null;<\/strong>\r\n\r\n\/\/ Handle creating\/removing shortcuts on Windows when installing\/uninstalling.\r\nif (require('electron-squirrel-startup')) {\r\n  app.quit();\r\n}\r\n\r\nconst createWindow = (): void =&gt; {\r\n  \/\/ Create the browser window.\r\n  mainWindow = new BrowserWindow({\r\n    width: 800,\r\n    height: 600,\r\n    webPreferences: {\r\n      preload: path.join(__dirname, 'preload.js'),\r\n    },\r\n  });\r\n\r\n  \/\/ and load the index.html of the app.\r\n  if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {\r\n    mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL);\r\n  } else {\r\n    mainWindow.loadFile(path.join(__dirname, `..\/renderer\/${MAIN_WINDOW_VITE_NAME}\/index.html`));\r\n  });\r\n\r\n  \/\/ Open the DevTools.\r\n  \/\/ mainWindow.webContents.openDevTools();\r\n\r\n<strong>  mainWindow.on(\"ready-to-show\", () =&gt; {\r\n    if (!mainWindow) {\r\n      throw new Error('\"mainWindow\" is not defined');\r\n    }\r\n    if (process.env.START_MINIMIZED) {\r\n      mainWindow.minimize();\r\n    } else {\r\n      mainWindow.show();\r\n    }\r\n  });\r\n\r\n  mainWindow.on(\"closed\", () =&gt; {\r\n    mainWindow = null;\r\n  });<\/strong>\r\n};\r\n\r\n\/\/ This method will be called when Electron has finished\r\n\/\/ initialization and is ready to create browser windows.\r\n\/\/ Some APIs can only be used after this event occurs.\r\napp.on('ready', createWindow);\r\n\r\n\/\/ Quit when all windows are closed, except on macOS. There, it's common\r\n\/\/ for applications and their menu bar to stay active until the user quits\r\n\/\/ explicitly with Cmd + Q.\r\napp.on('window-all-closed', () =&gt; {\r\n  if (process.platform !== 'darwin') {\r\n    app.quit();\r\n  }\r\n});\r\n\r\napp.on('activate', () =&gt; {\r\n  \/\/ On OS X it's common to re-create a window in the app when the\r\n  \/\/ dock icon is clicked and there are no other windows open.\r\n  if (BrowserWindow.getAllWindows().length === 0) {\r\n    createWindow();\r\n  }\r\n});\r\n\r\n\/\/ In this file you can include the rest of your app's specific main process\r\n\/\/ code. You can also put them in separate files and import them here.\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>preload.ts \u3092\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u7de8\u96c6\u3002<\/p>\n<pre>$ vim preload.ts\r\n-----\r\n\/\/ See the Electron documentation for details on how to use preload scripts:\r\n\/\/ https:\/\/www.electronjs.org\/docs\/latest\/tutorial\/process-model#preload-scripts\r\n\r\nimport {\r\n  contextBridge,\r\n  ipcRenderer,\r\n} from \"electron\";\r\n\r\n\/\/ \u30ec\u30f3\u30c0\u30e9\u30fc\u30d7\u30ed\u30bb\u30b9\u3068\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u306e\u901a\u4fe1\u306f\u3053\u3061\u3089\u3067\u5b9a\u7fa9\u3059\u308b\r\nconst electronHandler = {\r\n  shell: {\r\n    execCmd: async (cmd: string): Promise =&gt; {\r\n      return await ipcRenderer.invoke(\"exec-cmd\", [cmd]);\r\n    },\r\n  },\r\n};\r\n\r\ncontextBridge.exposeInMainWorld(\"electron\", electronHandler);\r\n\r\nexport type ElectronHandler = typeof electronHandler;\r\n-----\r\n:wq\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>src\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u76f4\u4e0b\u306b preload.d.ts \u3092\u4f5c\u6210\u3002preload.ts\u3067\u5b9a\u7fa9\u3057\u3066\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3057\u305felectronHandler\u306e\u578b\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u3001winodow\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9\u306belectron\u578b\u3068\u3057\u3066\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n<pre>$ cd ..\/\r\n$ vim preload.d.ts\r\n-----\r\nimport { ElectronHandler } from \".\/main\/preload\";\r\n\r\ndeclare global {\r\n  \/\/ window\u304b\u3089preload\u3067\u5b9a\u7fa9\u3057\u305felectronHandler\u3092\u547c\u3073\u51fa\u305b\u308b\u3088\u3046\u306b\u578b\u3092\u8ffd\u52a0\r\n  interface Window {\r\n    electron: ElectronHandler;\r\n  }\r\n}\r\n\r\nexport {};\r\n-----\r\n:wq\r\n<\/pre>\n<p>\u3053\u308c\u3067\u30da\u30fc\u30b8\u304b\u3089Shell\u30b3\u30de\u30f3\u30c9\u6a5f\u80fd\u3092\u547c\u3073\u51fa\u3059\u6e96\u5099\u304c\u3067\u304d\u307e\u3057\u305f\u3002\u3064\u304e\u306brenderer\u306b\u30da\u30fc\u30b8\u3092\u4f5c\u3063\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mac\u3068 Electron Forge + React + MUI \u3067PC\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\uff08\u305d\u306e\uff13\uff09\u306e\u7d9a\u304d\u3067\u3059\u3002 \u3053\u3061\u3089\u3092\u53c2\u8003\u306b\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u3001OS\u306e\u4efb\u610fShell\u30b3\u30de\u30f3\u30c9\uff08ls\u3068\u304bdf\u3068\u304b\uff09\u3092\u5b9f\u884c\u3057\u8868\u793a\u3059\u308b\u6a5f\u80fd\u3092\u4f5c\u6210\u3057\u3066\u307f &hellip; <a href=\"https:\/\/ji0vwl.net\/index.php\/2024\/03\/02\/3659\/\" class=\"more-link\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"screen-reader-text\">Mac\u3068 Electron Forge + React + MUI \u3067PC\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\uff08\u305d\u306e\uff14\uff09<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,19],"tags":[],"class_list":["post-3659","post","type-post","status-publish","format-standard","hentry","category-electron","category-19"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/posts\/3659","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/comments?post=3659"}],"version-history":[{"count":0,"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/posts\/3659\/revisions"}],"wp:attachment":[{"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/media?parent=3659"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/categories?post=3659"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ji0vwl.net\/index.php\/wp-json\/wp\/v2\/tags?post=3659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}