Microsoft MVP성태의 닷넷 이야기
.NET Framework: 1021. C# - 일렉트론 닷넷(Electron.NET) 소개 [링크 복사], [링크+제목 복사]
조회: 10609
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

C# - 일렉트론 닷넷(Electron.NET) 소개

말로만 들어오던 일렉트론을 이참에 강의도 있고 하니,

[.NET Conf 2021 x Seoul] 일렉트론 닷넷을 이용한 크로스 플랫폼 데스크톱 앱 개발 (동영상 25분)
; https://www.youtube.com/watch?v=I0MxOB9BX-U

ElectronNET/Electron.NET
; https://github.com/electronnet/electron.net

따라 해봤습니다. ^^




그러고 보니, 지난 글에 Razor 페이지를 호스팅하도록 변경한 콘솔 프로젝트 예제가 있군요. ^^

.NET Core Kestrel 호스팅 - Razor 지원 추가
; https://www.sysnet.pe.kr/2/0/12510

이를 재활용해(혹은, 그냥 일반적인 ASP.NET Core Web Application 프로젝트를 만들어) Electron.NET을 적용해 보겠습니다. 우선, 해당 프로젝트가 .NET Core 3.1로 맞춰져 있으니 이를 ".NET 5.0"으로 바꾼 다음, 패키지 참조를 추가합니다.

// 오늘자 기준 11.5.1 버전은 .NET 5 환경 요구

Install-Package ElectronNET.API

이후 Electron.NET으로써 동작하도록 코드 변경을 합니다.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using ElectronNET.API;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseElectron(args);

                // ...[생략]...

                webBuilder.UseStartup<Startup>();
            });
}

public class Startup
{
    // ...[생략]...

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...[생략]...

        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapRazorPages();

            if (HybridSupport.IsElectronActive)
            {
                CreateWindow();
            }
        });
    }

    private async void CreateWindow()
    {
        var window = await Electron.WindowManager.CreateWindowAsync();
        window.OnClosed += () =>
        {
            Electron.App.Quit();
        };
    }
}

여기까지만 마치고 실행하면 HybridSupport.IsElectronActive 속성이 false를 반환하므로 일반적인 Web Application과 다를 게 없습니다. IsElectronActive 속성을 true가 나오게 하려면 우선 적절한 매니페스트 파일이 필요합니다. 이 작업을 쉽게 하기 위해 ElectronNet.CLI 도구를 설치하고,

C:\Windows\System32> dotnet tool install -g ElectronNet.CLI
You can invoke the tool using the following command: electronize
Tool 'electronnet.cli' (version '11.5.1') was successfully installed.

C:\Windows\System32> dotnet tool list -g
Package Id                        Version                  Commands
-----------------------------------------------------------------------------
electronnet.cli                   11.5.1                   electronize

Web Application 프로젝트가 있는 디렉터리로 이동해 다음의 명령을 실행합니다.

C:\temp\ConsoleApp1> electronize init
Adding our config file to your project...
Search your .csproj/fsproj to add the needed electron.manifest.json...
Found your .csproj: C:\temp\ConsoleApp1\ConsoleApp1.csproj - check for existing config or update it.
electron.manifest.json will be added to csproj/fsproj.
electron.manifest.json added in csproj/fsproj!
Search your .launchSettings to add our electron debug profile...
Debug profile added!
Everything done - happy electronizing!

그럼 "electron.manifest.json" 파일이 생성되고, 마지막으로 "electronize start" 명령어를 실행하면 Electron 응용 프로그램으로써 빌드/실행됩니다.

C:\temp\ConsoleApp1> electronize start
Start Electron Desktop Application...
Microsoft Windows [Version 10.0.19042.746]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\temp\ConsoleApp1>dotnet publish -r win-x64 -c "Debug" --output "C:\temp\ConsoleApp1\obj\Host\bin" /p:PublishReadyToRun=true /p:PublishSingleFile=true --no-self-contained
Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
  Determining projects to restore...
  Restored C:\temp\ConsoleApp1\ConsoleApp1.csproj (in 14.82 sec).
  ConsoleApp1 -> C:\temp\ConsoleApp1\bin\Debug\net5.0\win-x64\ConsoleApp1.dll
  ConsoleApp1 -> C:\temp\ConsoleApp1\bin\Debug\net5.0\win-x64\ConsoleApp1.Views.dll
  ConsoleApp1 -> C:\temp\ConsoleApp1\obj\Host\bin\
C:\temp\ConsoleApp1>
node_modules missing in: C:\temp\ConsoleApp1\obj\Host\node_modules
Start npm install...
Microsoft Windows [Version 10.0.19042.746]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\temp\ConsoleApp1\obj\Host>npm install
npm WARN deprecated tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.
npm WARN deprecated debug@4.1.1: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)
> core-js@3.8.3 postinstall C:\temp\ConsoleApp1\obj\Host\node_modules\core-js
> node -e "try{require('./postinstall')}catch(e){}"
Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!
The project needs your help! Please consider supporting of core-js on Open Collective or Patreon:
> https://opencollective.com/core-js
> https://www.patreon.com/zloirock
Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)
> electron@11.2.1 postinstall C:\temp\ConsoleApp1\obj\Host\node_modules\electron
> node install.js
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN ws@7.4.2 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.
npm WARN ws@7.4.2 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.
added 188 packages from 162 contributors and audited 188 packages in 36.437s
found 0 vulnerabilities
C:\temp\ConsoleApp1\obj\Host>
ElectronHostHook handling started...
Invoke electron.cmd - in dir: C:\temp\ConsoleApp1\obj\Host\node_modules\.bin
Microsoft Windows [Version 10.0.19042.746]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\temp\ConsoleApp1\obj\Host\node_modules\.bin>electron.cmd "..\..\main.js"
Electron Socket IO Port: 8000
Electron Socket started on port 8000 at 127.0.0.1
ASP.NET Core Port: 8001
stdout: Use Electron Port: 8000
stdout: info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[63]
      User profile is available. Using 'C:\Users\SeongTae Jeong\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
stdout: warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Overriding address(es) 'http://localhost:8001'. Binding to endpoints defined in UseKestrel() instead.
stdout: info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://[::]:16000
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://[::]:16001
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://[::]:16002
stdout: ASP.NET Core host has fully started.
stdout: info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\temp\ConsoleApp1\obj\Host\bin
ASP.NET Core Application connected... global.electronsocket _r7hQkoWyYtVIJGEAAAA 2021-01-27T04:16:07.748Z
stdout: BridgeConnector connected!
(node:24964) electron: The default of contextIsolation is deprecated and will be changing from false to true in a future release of Electron.  See https://github.com/electron/electron/issues/23506 for more information
Got disconnect! Reason: transport close
ASP.NET Core Application connected... global.electronsocket _r7hQkoWyYtVIJGEAAAA 2021-01-27T04:16:40.853Z
stdout: BridgeConnector connected!

위의 출력에도 나오지만, 최초 실행할 때는 빌드를 비롯해 다소 준비 과정이 많아 느리지만, 다음번 실행은 좀 더 빠릅니다. (사실, 그래도 일반적인 응용 프로그램에 비하면 느립니다.)

다음은 이 글의 예제 프로그램이 실행된 모습입니다.

electron_net_1.png




위에서 빈 화면이 나온 것은, Electron이 사용하는 기본 포트가 있기 때문입니다. 따라서, 별도로 호출한 ListenAnyIP를 제거해,

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseElectron(args);})

            // webBuilder.ConfigureKestrel(options =>
            // {
            //     // HTTP/1.1 지원
            //     options.ListenAnyIP(16000, (httpOpt) =>
            //     {
            //     });
            // 
            //     // HTTP/2.0 over cleartext 지원
            //     options.ListenAnyIP(16001, (httpOpt) =>
            //     {
            //         httpOpt.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
            //     });
            // 
            //     // HTTP/2.0 over TLS 지원
            //     options.ListenAnyIP(16002, (httpsOpt) =>
            //     {
            //         httpsOpt.UseHttps();
            //     });
            // });

            webBuilder.UseStartup<Startup>();
        });

기본 포트(예제에서는 8001)가 사용되도록 만든 후 실행하면 이제야 index.cshtml 페이지가 담고 있는 내용을 화면에 띄웁니다.

electron_net_2.png




그 외에 필요한 만큼 응용 프로그램이 완성되었으면 이제 "electronize start"가 아닌, 명령행 자체에서 실행할 수 있는 바이너리를 생산할 차례입니다.

electronize build /target win-x64 /PublishReadyToRun false

이렇게 빌드하면 "/bin/Desktop/win-unpacked" 폴더가 생성되고 그 안에 (123 MB에 달하는) "ConsoleApp1.exe"를 비롯해 독립 실행에 필요한 파일들이 모두 출력되어 있습니다. (또한 설치 파일도 함께 "/bin/Desktop" 폴더에 "ConsoleApp1 Setup 1.0.0.exe"라는 형식의 이름으로 생성됩니다.)

그런데, 여기서 문제가 있군요. ^^; 현실적으로 봤을 때 저렇게 생성된 ConsoleApp1.exe를 사용자들이 실행하게 된다는 건데, 초기 로딩 속도가 너~~~무 느립니다. 그래서, 예를 들어 하루에 한 번 정도 실행해 두고 계속 유지하는 식의 프로그램이라면 괜찮을 듯싶은데, 메모장처럼 수시로 실행 및 종료를 반복하는 형태의 응용 프로그램에는 적합하지 않습니다. (물론, 인내심이 있다면 그런 영역도 적합하겠지만! ^^)

그래서, 더 살펴보지는 않고 이쯤에서 글을 마칩니다. ^^;

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 7/12/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2021-02-28 02시33분
[정환] 마이크로소프트에서 크로스플랫폼에 공을 많이 들이는건지 일렉트론닷넷, Blazor Client SPA, Uno 까지 정말 다양한것 같습니다.
일렉트론에 관심이 있었는데 닷넷으로 가능하다하니 관심있게 보았습니다. 동영상을 보는 내내 Blazor SPA와 거의 흡사한 느낌을 받았습니다.
[guest]

... 16  17  18  19  20  21  22  23  24  25  26  27  28  [29]  30  ...
NoWriterDateCnt.TitleFile(s)
12902정성태1/7/20227317오류 유형: 779. SQL 서버 로그인 에러 - provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.
12901정성태1/5/20227357오류 유형: 778. C# - .NET 5+에서 warning CA1416: This call site is reachable on all platforms. '...' is only supported on: 'windows' 경고 발생
12900정성태1/5/20229025개발 환경 구성: 622. vcpkg로 ffmpeg를 빌드하는 경우 생성될 구성 요소 제어하는 방법
12899정성태1/3/20228519개발 환경 구성: 621. windbg에서 python 스크립트 실행하는 방법 - pykd (2)
12898정성태1/2/20229062.NET Framework: 1129. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 인코딩 예제(encode_video.c) [1]파일 다운로드1
12897정성태1/2/20227931.NET Framework: 1128. C# - 화면 캡처한 이미지를 ffmpeg(FFmpeg.AutoGen)로 동영상 처리 [4]파일 다운로드1
12896정성태1/1/202210808.NET Framework: 1127. C# - FFmpeg.AutoGen 라이브러리를 이용한 기본 프로젝트 구성파일 다운로드1
12895정성태12/31/20219292.NET Framework: 1126. C# - snagit처럼 화면 캡처를 연속으로 수행해 동영상 제작 [1]파일 다운로드1
12894정성태12/30/20217230.NET Framework: 1125. C# - DefaultObjectPool<T>의 IDisposable 개체에 대한 풀링 문제 [3]파일 다운로드1
12893정성태12/27/20218791.NET Framework: 1124. C# - .NET Platform Extension의 ObjectPool<T> 사용법 소개파일 다운로드1
12892정성태12/26/20216773기타: 83. unsigned 형의 이전 값이 최댓값을 넘어 0을 지난 경우, 값의 차이를 계산하는 방법
12891정성태12/23/20216726스크립트: 38. 파이썬 - uwsgi의 --master 옵션
12890정성태12/23/20216843VC++: 152. Golang - (문자가 아닌) 바이트 위치를 반환하는 strings.IndexRune 함수
12889정성태12/22/20219265.NET Framework: 1123. C# - (SharpDX + DXGI) 화면 캡처한 이미지를 빠르게 JPG로 변환하는 방법파일 다운로드1
12888정성태12/21/20217440.NET Framework: 1122. C# - ImageCodecInfo 사용 시 System.Drawing.Image와 System.Drawing.Bitmap에 따른 Save 성능 차이파일 다운로드1
12887정성태12/21/20219512오류 유형: 777. OpenCVSharp4를 사용한 프로그램 실행 시 "The type initializer for 'OpenCvSharp.Internal.NativeMethods' threw an exception." 예외 발생
12886정성태12/20/20217452스크립트: 37. 파이썬 - uwsgi의 --enable-threads 옵션 [2]
12885정성태12/20/20217712오류 유형: 776. uwsgi-plugin-python3 환경에서 MySQLdb 사용 환경
12884정성태12/20/20216761개발 환경 구성: 620. Windows 10+에서 WMI root/Microsoft/Windows/WindowsUpdate 네임스페이스 제거
12883정성태12/19/20217614오류 유형: 775. uwsgi-plugin-python3 환경에서 "ModuleNotFoundError: No module named 'django'" 오류 발생
12882정성태12/18/20216728개발 환경 구성: 619. Windows Server에서 WSL을 위한 리눅스 배포본을 설치하는 방법
12881정성태12/17/20217238개발 환경 구성: 618. WSL Ubuntu 20.04에서 파이썬을 위한 uwsgi 설치 방법 (2)
12880정성태12/16/20217026VS.NET IDE: 170. Visual Studio에서 .NET Core/5+ 역어셈블 소스코드 확인하는 방법
12879정성태12/16/202113274오류 유형: 774. Windows Server 2022 + docker desktop 설치 시 WSL 2로 선택한 경우 "Failed to deploy distro docker-desktop to ..." 오류 발생
12878정성태12/15/20218313개발 환경 구성: 617. 윈도우 WSL 환경에서 같은 종류의 리눅스를 다중으로 설치하는 방법
12877정성태12/15/20216979스크립트: 36. 파이썬 - pymysql 기본 예제 코드
... 16  17  18  19  20  21  22  23  24  25  26  27  28  [29]  30  ...