this repo has locked the main deps version:
[email protected]
,[email protected]
, so that you can keep the dev-env and runtime-env consistent as much as possible.
after considering various factors(capability in code development, app develop time, cost of code maintenance), have derived the best practices for developing cross-platform desktop applications.
- build and publish dotnet library
cd CrossPlatform.DesktopApp npm run build:dll
- install electron app deps
cd CrossPlatform.DesktopApp npm install
- start webpack dev server in electron app
cd CrossPlatform.DesktopApp npm run watch:render
- start tsc watch in electron app
cd CrossPlatform.DesktopApp npm run watch:main
- start electron app
cd CrossPlatform.DesktopApp npm run dev
recommend ways below
-
define a class and static method in usual sync syntax(not async/await)
using System; using System.Runtime; namespace CrossPlatform.Library { public class SystemUtils { public static string WhatIsTime() { string now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); return now; } } }
-
define a class and async method to call
the method in the step 1
fornode
using System; using System.Runtime; using System.Threading.Tasks; namespace CrossPlatform.Library { public class SystemUtils4Node { // WARN! WARN! WARN! // suggest define the parameter, even you don't need // just to avoid invoke Error public async Task<object> WhatIsTime(dynamic input) { string result = SystemUtils.WhatIsTime(); return result; } } }
-
use
electron-edge-js
to invoke(you can usemain-process/dll-bridge-invoke
directly)// relative path , split 【dotnet-dll】 directory and use the rest const assemblyPath = 'CrossPlatform.Library.dll'; // suggest to include namespace const className = 'CrossPlatform.Library.SystemUtils4Node'; const methodName = 'WhatIsTime'; dllBridgeInvoke(assemblyPath, className, methodName) .then((res) => console.info('res', res)) // res 2024-12-10 17:09:45.082 .catch((err) => console.error('err', err));
To simplify the logic, this project has encapsulated and streamlined several IPC communication APIs.
The APIs avoid the impact of broadcasting, meaning the relationship between window or view and their respective loaded views is
one-to-one binding
.
invoke / handle -> Corresponds to
ipcRenderer.invoke
andipcMain
.handle.on / send -> Corresponds to
ipcMain.on
、ipcRenderer.on
andipcMain.send
、ipcRenderer.send
The project introduces the concepts of
Art
,ArtWin
, andArtView
.Among these,
ArtWin
andArtView
can load views, so specific event communication exists on these two concepts.
Art
-> Base class of the application, responsible for managingArtWin
, i.e., managing the application’s main window.
ArtWin
-> Main window class, containing theBrowserWindow
instance, and is used to manageArtView
.
ArtView
-> View class, containing theBrowserView
instance, used in scenarios without an independent window.
// main-process
const mainWin: ArtWin = new ArtWin({
···
});
const connection: IConnection = mainWin.getConnection();
connection.on('art-ipc-evt-1', (evt, payload) => {
// payload = 'evt-1-from-render'
···
});
connection.send('art-ipc-evt-2', 'evt-2-from-main');
connection.handle('art-ipc-evt-3', async (evt, payload) => {
// payload = 'evt-2-from-render'
···
return 'evt-3-from-main';
});
// render-process
window.ipcClient.send('art-ipc-evt-1', 'evt-1-from-render');
window.ipcClient.on('art-ipc-evt-2', (evt, payload) => {
// payload = 'evt-2-from-main'
···
});
window.ipcClient
.invoke('art-ipc-evt-3', 'evt-3-from-render')
.then(res => {
// res = 'evt-3-from-main'
···
})
.catch(console.error)
-
CrossPlatform.DesktopApp
- main project as
desktop application
- published to
.dmg installer for Mac OS
,.exe installer for Windows OS
,.deb installer for Linux-based OS
- based on
[email protected]
- use
electron-edge-js
to invoke.dll
published by CrossPlatform.Library, so that you can leverage system-level APIs or capabilities at a very low cost
- main project as
-
CrossPlatform.Library
- project used to develop
class library
- published to
.dll
to be used inelectron nodejs runtime environment
invoked byelectron-edge-js
- based on
.net 8
- due to using
.net core
, so need to publish self-contained library for desktop app to use as expected in any platform
- project used to develop
-
CrossPlatform.LibTest
- project used to test CrossPlatform.Library
- a console application, supported
Windows OS
,Mac OS
,Linux-based OS
- based on
.net 8
-
(recommended in Windows) test in CrossPlatform.LibTest under Visual Studio IDE
# no need for shell, just open the solution file in Visual Studio IDE, then run the CrossPlatform.LibTest project
-
(any platform) test in CrossPlatform.LibTest under Terminal
cd CrossPlatform.LibTest dotnet run
-
(any platform) test in CrossPlatform.DesktopApp under nodejs runtime (not electron)
cd CrossPlatform.DesktopApp npm run test
TODO
fork
- replace
electron version
for your favorite - replace
.net version
for your favorite - replace
app name
、app icon
etc. in CrossPlatform.DesktopApp - add class library if needed, then publish in CrossPlatform.Library
- build and publish CrossPlatform.DesktopApp
-
sutck the step when install
electron-edge-js
andelectron
- make sure you've install
node-gyp
andnode-pre-gyp
- BTW, use
@mapbox/node-pre-gyp
- make sure you've install
-
stuck the step when install
node-gyp
andnode-pre-gyp
: idealTree buildDeps- try to run cmd
npm set strict-ssl false
to disable ipv6
- try to run cmd