Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yelhouti committed Aug 28, 2023
0 parents commit b8db839
Show file tree
Hide file tree
Showing 14 changed files with 408 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# vscode
.vscode
.history

# .net
obj/
bin/
temp/

# visual studio
*.user
.vs
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Scan Server

Scan server is a Free to use alternative to many expensive solutions out there that allow scanning documents from Web applications.

## Project Structure

There are two projects:
1. ScanServer: Compiles into a .exe that can be run a standalone app or as a service
2. ScanServerInstaller: Create an MSI to make easier to download and install as Windows Service (Runs by default on http://localhost:5000).

## How to use

Just run/install the app.
List the devices on: http://localhost:5000/api/scanners


## Getting started

To build this project:

```ps
cd .\ScanServer
rm -r .\bin\
dotnet clean
dotnet publish ScanServer.csproj -c Release
cd ..\ScanServerInstaller
rm -r .\bin\
dotnet clean
dotnet build -c Release
```


## Uninstall:

To uninstall start a command line as administrator and run:

```cmd
sc stop ScanServer
sc delete ScanServer
```

Then delete the install folder.

# Naps2

A huge thank you to @cyanfish and it's [NAPS2 SDK Project](https://github.com/cyanfish/naps2/) without whom/which building this would have taken a lot of time.
If you want to donate, please donate to him using this [link](https://www.naps2.com/donate?src=scan-server)

# TODO
Find a way to change the default port in the service either:
1. by configuring the service in the installer
2. Building the app with another default port while allowing --urls to work.
61 changes: 61 additions & 0 deletions ScanServer.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScanServer", "ScanServer\ScanServer.csproj", "{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}"
EndProject
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ScanServerInstaller", "ScanServerInstaller\ScanServerInstaller.wixproj", "{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|ARM64.Build.0 = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|x64.ActiveCfg = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|x64.Build.0 = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|x86.ActiveCfg = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Debug|x86.Build.0 = Debug|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|Any CPU.Build.0 = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|ARM64.ActiveCfg = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|ARM64.Build.0 = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|x64.ActiveCfg = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|x64.Build.0 = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|x86.ActiveCfg = Release|Any CPU
{E8BAF2B7-B5BC-4C85-AC30-F744962C7A51}.Release|x86.Build.0 = Release|Any CPU
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|Any CPU.ActiveCfg = Debug|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|Any CPU.Build.0 = Debug|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|ARM64.ActiveCfg = Debug|ARM64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|ARM64.Build.0 = Debug|ARM64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|x64.ActiveCfg = Debug|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|x64.Build.0 = Debug|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|x86.ActiveCfg = Debug|x86
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Debug|x86.Build.0 = Debug|x86
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|Any CPU.ActiveCfg = Release|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|Any CPU.Build.0 = Release|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|ARM64.ActiveCfg = Release|ARM64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|ARM64.Build.0 = Release|ARM64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|x64.ActiveCfg = Release|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|x64.Build.0 = Release|x64
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|x86.ActiveCfg = Release|x86
{ABE1D0C9-7C80-4C87-A3F5-00387BB43583}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B68A425-1030-4625-ABA9-A35B7C87464F}
EndGlobalSection
EndGlobal
64 changes: 64 additions & 0 deletions ScanServer/Controllers/ScannerController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NAPS2.Scan;
using NAPS2.Images;
using System.Drawing;
using NAPS2.Images.Gdi;
using System.IO;

namespace ScanServer.Controllers
{

[ApiController]
[Route("api")]
public class ScannerController : ControllerBase
{

private readonly ILogger<ScannerController> _logger;

private readonly ScanController _scanController;

public ScannerController(ILogger<ScannerController> logger)
{
this._logger = logger;
using ScanningContext scanningContext = new ScanningContext(new GdiImageContext());
scanningContext.SetUpWin32Worker();
_scanController = new ScanController(scanningContext);
}

[HttpGet("scanners")]
public async Task<ActionResult<List<ScanDevice>>> ListDevices()
{
_logger.LogDebug($"{nameof(ListDevices)}");
// TODO based on env Var change driver
// TODO set 32 or 64 based on OS
//var devices = await _scanController.GetDeviceList(new ScanOptions { Driver = Driver.Twain, TwainOptions = { Dsm = TwainDsm.Old, Adapter = TwainAdapter.Legacy } });
var devices = await _scanController.GetDeviceList(Driver.Twain);
return Ok(devices);
}

[HttpGet("scan/{deviceId}")]
public async Task<ActionResult> Scan([FromRoute] string deviceId)
{
_logger.LogDebug($"{nameof(Scan)}");
var devices = await _scanController.GetDeviceList(Driver.Twain);
ScanDevice device = devices.Find(d => d.ID == deviceId);
if (device == null)
{
return NotFound();
}
var scannedImages = _scanController.Scan(new ScanOptions { Device = device, Driver = Driver.Twain, Dpi = 200 }).ToBlockingEnumerable().ToList();
if (scannedImages.Count == 0)
{
return NotFound();
}
return processedImageToFile(scannedImages[0]);
}

private FileContentResult processedImageToFile(ProcessedImage processedImage)
{
var stream = processedImage.Render().SaveToMemoryStream(ImageFileFormat.Jpeg);
return File(stream.ToArray(), "image/jpeg");
}
}
}
70 changes: 70 additions & 0 deletions ScanServer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.Extensions.Hosting.WindowsServices;
using ScanServer.Controllers;
using System.Diagnostics;

ILogger<WebApplication> _logger;

var options = new WebApplicationOptions
{
Args = args,
// Setting to allow the service to run both in IDE and as service
ContentRootPath = WindowsServiceHelpers.IsWindowsService()
? AppContext.BaseDirectory
: default
};
var builder = WebApplication.CreateBuilder(options);
var isService = !(Debugger.IsAttached || args.Contains("--console"));
if (isService)
{
builder.Host.UseWindowsService();
}

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var allowedOrigins = args.SkipWhile(arg => arg != "--origins")
.Skip(1) // Skip the "--origins" argument itself
.ToList();
if (allowedOrigins.Count == 0)
{
allowedOrigins.Add("*"); // Set to wildcard if no origins specified
}

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.WithOrigins(allowedOrigins.ToArray())
.AllowAnyMethod()
.AllowAnyHeader();
});
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.MapGet("/", () =>
{
return "Scan Server is Running with:" + "\nargs: " + String.Join(' ', args) + "\nContentRootPath: "+ options.ContentRootPath + "\nService: " + isService;
});

app.MapControllers();
app.UseCors();

if (isService)
{
await app.RunAsync();
} else
{
app.Run();
}
41 changes: 41 additions & 0 deletions ScanServer/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:45941",
"sslPort": 44309
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5107",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7058;http://localhost:5107",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
26 changes: 26 additions & 0 deletions ScanServer/ScanServer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Exe</OutputType>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<PublishReadyToRun>true</PublishReadyToRun>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="7.0.10" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.10" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />

<PackageReference Include="NAPS2.Sdk" Version="0.1.0-alpha01" />
<PackageReference Include="NAPS2.Images.ImageSharp" Version="0.1.0-alpha01" />
<PackageReference Include="NAPS2.Images.Gdi" Version="0.1.0-alpha01" />
<PackageReference Include="NAPS2.Sdk.Worker.Win32" Version="0.1.0-alpha01" />
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions ScanServer/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions ScanServer/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
7 changes: 7 additions & 0 deletions ScanServerInstaller/Folders.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="ScanServer" />
</StandardDirectory>
</Fragment>
</Wix>
8 changes: 8 additions & 0 deletions ScanServerInstaller/Package.en-us.wxl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">

<String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />

</WixLocalization>
13 changes: 13 additions & 0 deletions ScanServerInstaller/Package.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="ScanServerInstaller" Manufacturer="Tailosoft SA" Version="1.0.0.0" UpgradeCode="9632595a-3ba4-4f28-8eb2-c6a54c813204">

<MediaTemplate EmbedCab="yes" />
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />

<Feature Id="Main">
<ComponentGroupRef Id="ScanServer" />
</Feature>


</Package>
</Wix>
Loading

0 comments on commit b8db839

Please sign in to comment.