---
title: "Integrating DocuVieware with Electron"
canonical_url: "https://www.nutrient.io/guides/docuvieware/other-technologies/integrating-docuvieware-with-electron/"
md_url: "https://www.nutrient.io/guides/docuvieware/other-technologies/integrating-docuvieware-with-electron.md"
last_updated: "2026-05-19T01:10:17.036Z"
description: "Integrate DocuVieware into your Electron app for cross-platform document management functionality."
---

# Integrating DocuVieware with Electron

Electron is a framework for building desktop applications using JavaScript, HTML, and CSS. By embedding Chromium and Node.js in its binary, Electron enables you to maintain a JavaScript codebase and build cross-platform applications that run on Windows, macOS, and Linux without native development experience.

## Preparing your environment

To create an Electron sample, you need to have [DocuVieware](https://www.nutrient.io/guides/dotnet/downloads.md#viewers), [Node.js](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs), and [Electron](https://www.electronjs.org/docs/tutorial/installation) installed on your machine. Use the latest LTS version available. DocuVieware requires at least the.NET Framework 4.6 or.NET Core 3.0 to run properly.

## Creating your Electron sample

At the end of this guide, you’ll have an Electron app with DocuVieware embedded within. The application enables you to use DocuVieware’s default features, choose the language of the viewer, and dynamically create a custom signature field and sign it.

Create a new folder, `DocuVieware-electron-sample` and within it, create another folder called `Client`.

Once the folders are created, launch the CMD and run the `npm init` command. Set the package name and the information asked by Node.js.

This command creates a `package.json` file for your project’s frontend. A `package.json` file contains information about the project’s packages and dependencies. It also contains metadata for the project, such as version number, author, and description. Once it’s done, launch `npm i --save-dev electron`. This adds the third-party package to the package’s development dependencies. In the `package.json`, under scripts, add `"start": "electron."` to set node scripts to run. Change the main parameter to `"app/server.js"`. Create an `app` folder, and add an `index.html` file with this HTML code to give your application a loading screen.

```html

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>DocuVieware Sample</title>
 <style>
 html,
 body {
 margin: 0px;
 }
 </style>
</head>
<body style="height: 100vh; width:100vw;">
<img src="https://www.pdfa.org/wp-content/uploads/2019/02/Logo_DocuVieware_no_version-wpv_x200.png" style="position: absolute; position: absolute; margin: auto; top: 0; left: 0; right: 0; bottom: 0;" />
</body>
</html>

```

Create a `server.js` file within the `app` folder, and add the code below to create the default window:

```javascript

const { app, BrowserWindow, Menu } = require('electron')
const path = require("path")
require('dotenv').config()
var win = null; function createWindow()
{
win = new BrowserWindow({ width: 800, height: 600 });
win.loadFile('app/index.html')
}
app.whenReady().then(createWindow)

```

In the `Client` folder, run the `npm i dotenv` command in the CMD. At this step, if you run `npm start`, the app should load with the DocuVieware image.

## Integrating DocuVieware

Create a `Server` folder beside the `Client` one, and create a Visual Studio project within. Run Visual Studio and click **Create a new project**. Choose the **ASP.NET Core Empty** project.

Give your project a name and choose the **Server** folder as a location. Then click **Next**. Choose a target framework (4.6 or higher) and click **Create**.

Add the reference to `GdPicture.NET.14.WEB.DocuVieware.Core.dll` found in: `[INSTALLATION FOLDER]\Redist\DocuVieware (.NET Core 3.0)`.

It’s also required to add `Microsoft.AspNetCore.Mvc.NewtonsoftJson` with NuGet manager.

Now that the references are properly set, create a **Controllers** folder and add a `DocuVieware3Controller.cs` file in your project to add some mandatory imports and handle the licensing part and the configuration part of DocuVieware:

```csharp

using Microsoft.AspNetCore.Mvc;
using GdPicture14.WEB;
using System.Net.Http;
using System.Net;
namespace DocuViewareElectronServer.Controllers
{
 [Route("api/docuvieware3")]
 public class DocuVieware3Controller : Controller
 {
 [HttpGet("ping")]
 public string ping()
 {
 return "pong";
 }

 [HttpPost("baserequest")]
 public string baserequest([FromBody] object jsonString)
 {
 return DocuViewareControllerActionsHandler.baserequest(jsonString);
 }

 [HttpGet("print")]
 public HttpResponseMessage Print(string sessionID, string pageRange, bool printAnnotations)
 {
 return DocuViewareControllerActionsHandler.print(sessionID, pageRange, printAnnotations);
 }

 [HttpGet("save")]
 public IActionResult Save(string sessionID, string fileName, string format, string pageRange, bool dropAnnotations, bool flattenAnnotations)
 {
 DocuViewareControllerActionsHandler.save(sessionID, ref fileName, format, pageRange,dropAnnotations, flattenAnnotations, out HttpStatusCode statusCode, out string reasonPhrase, out byte[] content, out string contentType);
 if (statusCode == HttpStatusCode.OK)
 {
 return File(content, contentType, fileName);
 }
 else
 {
 return StatusCode((int)statusCode, reasonPhrase);
 }
 }

 [HttpGet("twainservicesetupdownload")]
 public IActionResult TwainServiceSetupDownload(string sessionID)
 {
 DocuViewareControllerActionsHandler.twainservicesetupdownload(sessionID, out HttpStatusCode statusCode, out byte[] content, out string contentType, out string fileName, out string reasonPhrase);
 if (statusCode == HttpStatusCode.OK)
 {
 return File(content, contentType, fileName);
 }
 else
 {
 return StatusCode((int)statusCode, reasonPhrase);
 }
 }

 [HttpPost("formfieldupdate")]
 public string FormfieldUpdate([FromBody]object jsonString)
 {
 return DocuViewareControllerActionsHandler.formfieldupdate(jsonString);
 }

 [HttpPost("annotupdate")]
 public string AnnotUpdate([FromBody]object jsonString)
 {
 return DocuViewareControllerActionsHandler.annotupdate(jsonString);
 }

 [HttpPost("loadfromfile")]
 public string LoadFromFile([FromBody]object jsonString)
 {
 return DocuViewareControllerActionsHandler.loadfromfile(jsonString);
 }

 [HttpPost("loadfromfilemultipart")]
 public string LoadFromFileMultipart()
 {
 return DocuViewareControllerActionsHandler.loadfromfilemultipart(Request);
 }
 }
}

```

In the `Startup.cs` file, add the following application URI and the DocuVieware basic configuration:

```csharp

const string APP_URI = "http://localhost:5000";
public Startup(IConfiguration configuration)
{
DocuViewareLicensing.RegisterKEY("YOUR_KEY_HERE");
 Configuration = configuration;
 DocuViewareManager.SetupConfiguration(true, Globals.DOCUVIEWARE_SESSION_STATE_MODE, Path.Combine(Globals.GetCacheDirectory(), "/", "api/docuvieware3"), APP_URI, "api/docuvieware3");
 DocuViewareEventsHandler.CustomAction += Globals.CustomActionHandler;
}

```

Enable CORS:

```csharp

public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
 services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
 if (env.IsDevelopment())
 {
 app.UseDeveloperExceptionPage();
 }
 app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()
 );
 app.UseRouting();
 app.UseAuthorization();
 app.UseEndpoints(endpoints =>
 {
 endpoints.MapControllers();
 });
}

```

Create a **Models** folder, and then create a `DocuViewareConfiguration` class in it to manage the `SessionId` and `ControlId`:

```csharp

namespace DocuViewareElectronServer.Models
{
 public class DocuViewareConfiguration
 {
 public string SessionId { get; set; }
 public string ControlId { get; set; }
 }
}

```

Create a `DocuViewareRESTOutputResponse` class in the model folder, and declare the `HtmlContent` that’s communicated between the client and the server:

```csharp

namespace DocuViewareElectronServer.Models
{
 public class DocuViewareRESTOutputResponse
 {
 public string HtmlContent { get; set; }
 }
}

```

Create a new controller, `DocuViewareController`:

```csharp

namespace DocuViewareElectronServer.Controllers
{
 public class DocuViewareController : Controller
 {
 [HttpPost]
 [Route("GetDocuViewareControl")]
 public DocuViewareRESTOutputResponse GetDocuViewareControl(DocuViewareConfiguration controlConfiguration)
 {
 if (!DocuViewareManager.IsSessionAlive(controlConfiguration.SessionId))
 {
 if (!string.IsNullOrEmpty(controlConfiguration.SessionId) &&!string.IsNullOrEmpty(controlConfiguration.ControlId))
 {
 DocuViewareManager.CreateDocuViewareSession(controlConfiguration.SessionId, controlConfiguration.ControlId, 20);
 }
 else
 {
 throw new Exception("Invalid session identifier and/or invalid control identifier.");
 }
 }

 using (DocuViewareControl docuVieware = new DocuViewareControl(controlConfiguration.SessionId))
 {
 docuVieware.MaxUploadSize = 36700160; // 35MB
 docuVieware.ShowDigitalSignatureSnapIn = true;

 using (StringWriter controlOutput = new StringWriter())
 {
 docuVieware.RenderControl(controlOutput);
 DocuViewareRESTOutputResponse output = new DocuViewareRESTOutputResponse
 {
 HtmlContent = controlOutput.ToString()
 };
 return output;
 }
 }
 }
 }
}

```

Create a new class file called `Globals` and add the lines below:

```csharp

using GdPicture14;
using GdPicture14.WEB;
using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace DocuViewareElectronServer
{
 public static class Globals
 {
 private static readonly string m_rootDirectory = Directory.GetCurrentDirectory();
 public static readonly int SESSION_TIMEOUT = 20;
 public const bool STICKY_SESSION = true;
 public const DocuViewareSessionStateMode DOCUVIEWARE_SESSION_STATE_MODE = DocuViewareSessionStateMode.File;

 public static string GetCacheDirectory()
 {
 return m_rootDirectory + "\\cache";
 }

 public static string GetDocumentsDirectory()
 {
 return m_rootDirectory + "\\documents";
 }

 public static string BuildDocuViewareControlSessionID(HttpContext HttpContext, string clientID)
 {
 if (HttpContext.Session.GetString("DocuViewareInit") == null)
 {
 HttpContext.Session.SetString("DocuViewareInit", "true");
 }

 return HttpContext.Session.Id + clientID;
 }
 }
}

```

Create a `.env` file, and set your hostname and port:

```text

SERVER_SCHEME=http
SERVER_HOSTNAME=localhost
SERVER_PORT=5000

```

Add the line below as the first line of the `server.js` file:

```javascript

require('dotenv').config()

```

Add the following object in the `BrowserWindow` constructor (`server.js`):

```javascript

webPreferences: {
 preload: path.join(__dirname, 'preload.js'),
 nodeIntegration: true,
 contextIsolation: false,
 webSecurity: false
 }

```

Add a `preload.js` file and add the following lines to manage the preload process of your application:

```javascript

import { ipcRenderer } from 'electron';
window.addEventListener('DOMContentLoaded', () => {
window.processId = `${process.pid}`;
ipcRenderer.emit("preload-done"); });

```

Create an `index.js` file and add the code below to wait until the end of the preload script to launch the application and let Electron execute the JavaScript:

```javascript

import { ipcRenderer } from 'electron';

//We have to wait the end of the preload script to start the app
ipcRenderer.once('preload-done', () => launchControl());

//This is necessary because when we set the dv control in the innerHTML of a HTMLElement, electron does not execute the JS inside
const evalPageScripts = () => {
 const scripts = document.querySelectorAll('#dvcontrol script');

 scripts.forEach((script) => {
 const newScript = document.createElement('script');
 newScript.type = 'text/javascript';
 newScript.innerText = script.innerText;

 if (script.parentNode) {
 script.parentNode.removeChild(script);
 }
 return document.body.appendChild(newScript);
 })
};

//Get the DV control from the server and display it in the window
function launchControl() {
 fetch(${process.env.SERVER_SCHEME}:/${process.env.SERVER_HOSTNAME}:${process.env.SERVER_PORT}/api/DocuVieware/GetDocuViewareControl, {
 method: 'POST',
 body: JSON.stringify({
 SessionId: ${window.processId},
 ControlId: "dvcontrol"
 }),
 headers: new Headers({
 "Content-Type": "application/json"
 })
 }).then(response => response.json()).then(result => {
 document.body.innerHTML = result.htmlContent;
 evalPageScripts();
 });
}

```

The `evalpagescripts` method is needed because when raw HTML is added to the DOM, Electron doesn’t evaluate script tags. Create an `asset` folder and copy-paste the `min-js/min-css` from the `redist`. In the head of `index.html`, add:

```html

<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="assets/docuvieware-min.js"></script>
<link rel="stylesheet" href="assets/docuvieware-min.css">
<script src="./index.js"></script>

```

At this point, if you run the server through Visual Studio and the client by running it through the command `npm start` in the CMD, the DocuVieware control should be displayed in Electron’s window.

## Adding the switch language feature

Go to the `DocuViewareConfiguration` class in the `DocuViewareConfiguration.cs` file, and add the following property:

```csharp

public DocuViewareLocale Lang { get; set; }

```

In the `GetDocuViewareControl` method, add the following line:

```csharp

docuVieware.Locale = controlConfiguration.Lang;

```

In the `DocuViewareController.cs` file, add a method that returns the supported DocuVieware languages:

```csharp

[HttpGet]
 [Route("GetDocuviewareLanguages")]
 public IActionResult GetSupportedLanguages()
 {
 var languages = new List<string>();
 foreach (var lang in Enum.GetValues(typeof(DocuViewareLocale)))
 {
 if ((DocuViewareLocale)lang == DocuViewareLocale.Auto)
 {
 continue;
 }

 languages.Add($"{(int)lang}|{lang}");
 }
 return Ok(languages);
 }

```

To send requests, install `electron-fetch` with this command: `npm i --save electron-fetch`. In the `createwindow` method in the `Server.js` file, add the following method after the `win` affectation. It gets the available DocuVieware language list sent by the previous method:

```javascript

fetch(`${process.env.SERVER_SCHEME}://${process.env.SERVER_HOSTNAME}:${process.env.SERVER_PORT}/api/DocuVieware/GetDocuviewareLanguages`).then(response => response.json()).then(result => {
 var languages = [];
 result.forEach(lang => {
 var infos = lang.split('|');
 var code = parseInt(infos[0]);
 var label = infos[1];
 languages.push({
 label: label,
 click: () => changeControlLang(code)
 })
 });
 let menu = Menu.buildFromTemplate([
 {
 label: 'Lang',
 submenu: languages
 },
 {
 label: "Dev",
 submenu: [{
 label: "DevTool",
 role: 'toggleDevTools'
 },{
 label: "Reload",
 role: 'reload'
 }]
 }
 ]);
 Menu.setApplicationMenu(menu);
 }).catch(console.error);

```

Add the code below in the `index.js` file to get the event of a language change:

```javascript

//Get language change event from the menu and reload control
ipcRenderer.on('change-lang', function (event, lang) {
 launchControl(lang);
});

```

To support the language management on the client-side, replace the `loadControl` method with the following:

```javascript

//Get the DV control from the server and display it in the window
function launchControl(lang) {
 //if no lang is provided, use Auto
 if (!lang) {
 lang = 0;
 }
 fetch(${process.env.SERVER_SCHEME}:/${process.env.SERVER_HOSTNAME}:${process.env.SERVER_PORT}/api/DocuVieware/GetDocuViewareControl, {
 method: 'POST',
 body: JSON.stringify({
 SessionId: ${window.processId},
 ControlId: "dvcontrol",
 Lang: lang
 }),
 headers: new Headers({
 "Content-Type": "application/json"
 })
 }).then(response => response.json()).then(result => {
 document.body.innerHTML = result.htmlContent;
 evalPageScripts();
 });
}

```

Run both server and client, and a new menu should be displayed and offer to change the DocuVieware language.

## Adding the custom signature field feature

On the server-side, in the `Startup.cs` file, add a `CustomActionHandler` event to let your client communicate with a custom server method:

```csharp

DocuViewareEventsHandler.CustomAction += Globals.CustomActionHandler;

```

Add the method in the `Global.cs` file with the custom creation of a `Signature` field:

```csharp

public static void CustomActionHandler(object sender, CustomActionEventArgs e)
{
 var status = e.docuVieware.GetNativePDF(out GdPicturePDF pdf);

 if (status!= GdPictureStatus.OK)
 {
 e.message = new DocuViewareMessage("The document is not a PDF!");
 return;
 }

 switch (e.actionName)
 {
 case "AddSignatureFormField":
 //The GetSelectionAreaCoordinates return value in Inch
 pdf.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitInch);
 pdf.SetOrigin(PdfOrigin.PdfOriginTopLeft);

 var addSignatureFormFieldArgs = JsonSerializer.Deserialize<PostCustomActionModels.AddSignatureFormFieldModel>(
 e.args.ToString(),
 new JsonSerializerOptions { PropertyNameCaseInsensitive = true, NumberHandling = JsonNumberHandling.Strict });

 pdf.AddSignatureFormField(
 addSignatureFormFieldArgs.Region.Left,
 addSignatureFormFieldArgs.Region.Top,
 addSignatureFormFieldArgs.Region.Width,
 addSignatureFormFieldArgs.Region.Height,
 addSignatureFormFieldArgs.FormFieldName);

 status = pdf.GetStat();

 if (status!= GdPictureStatus.OK)
 {
 e.message = new DocuViewareMessage("The signature could not be added");
 return;
 }

 pdf.DrawRectangle(
 addSignatureFormFieldArgs.Region.Left,
 addSignatureFormFieldArgs.Region.Top,
 addSignatureFormFieldArgs.Region.Width,
 addSignatureFormFieldArgs.Region.Height,
 false,
 true);

 e.docuVieware.RedrawPage();

 break;
 }
}

```

To define the area where the signature field should be placed, create a custom class:

```csharp

public static class PostCustomActionModels
{
 public class AddSignatureFormFieldModel
 {
 public string FormFieldName { get; set; }
 public Region Region { get; set; }
 }

 public class Region
 {
 public float Width { get; set; }
 public float Height { get; set; }
 public float Top { get; set; }
 public float Left { get; set; }
 }
}

```

## Running the application

Launch your sample by running the server through Visual Studio, and launch `npm start` through the CMD on the Electron project.

You can find the complete sample in the installation folder of DocuVieware on your machine.![Electron application showing DocuVieware with language selection menu](@/assets/guides/docuvieware/dv-electron6.png)

Change the DocuVieware default language through Electron’s main menu.

## Related guides

- [Serving DocuVieware through a REST API](https://www.nutrient.io/guides/docuvieware/other-technologies/serving-docuvieware-through-a-rest-api.md)

- [Client/server coming and going with custom actions](https://www.nutrient.io/guides/docuvieware/other-technologies/rest-client-server-coming-and-going-with-custom-actions.md)

- [Custom snap-in implementation](https://www.nutrient.io/guides/docuvieware/other-technologies/rest-custom-snap-in-implementation.md)
---

## Related pages

- [Introduction](/guides/docuvieware/other-technologies.md)
- [DocuVieware guide for Blazor](/guides/docuvieware/other-technologies/docuvieware-tutorial-for-blazor.md)
- [Integrating DocuVieware in your AngularJS client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-angularjs-client-application.md)
- [How to set up and use DocuVieware with React](/guides/docuvieware/other-technologies/how-to-set-up-and-use-docuvieware-with-react.md)
- [Integrating DocuVieware in your Angular2 client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-angular2-client-application.md)
- [Integrating DocuVieware in your JavaScript/jQuery client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-javascript-jquery-client-application.md)
- [Integrating DocuVieware in your ASP.NET Core MVC Razor client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-asp-dotnet-core-mvc-razor-client-application.md)
- [Integrating DocuVieware in your Java client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-java-client-application.md)
- [Integrating DocuVieware in your Node.js client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-nodejs-client-application.md)
- [Client/server coming and going with custom actions](/guides/docuvieware/other-technologies/rest-client-server-coming-and-going-with-custom-actions.md)
- [Integrating DocuVieware in your PHP client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-php-client-application.md)
- [Integrating DocuVieware in your ASP.NET MVC Razor client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-asp-dotnet-mvc-razor-client-application.md)
- [Use and handling of the selection area](/guides/docuvieware/other-technologies/rest-use-and-handling-of-the-selection-area.md)
- [Integrating DocuVieware into SharePoint 2019](/guides/docuvieware/other-technologies/integrating-docuvieware-into-sharepoint-2019.md)
- [Serving DocuVieware through a REST API](/guides/docuvieware/other-technologies/serving-docuvieware-through-a-rest-api.md)
- [Custom snap-in implementation](/guides/docuvieware/other-technologies/rest-custom-snap-in-implementation.md)
- [Your first Angular 10 application with DocuVieware](/guides/docuvieware/other-technologies/your-first-angular-10-application-with-docuvieware.md)

