2 Commits

Author SHA1 Message Date
308966da36 Upgrade to .NET 8 LTS and enhance installer functionality
- Upgraded from .NET 7 to .NET 8 LTS for better Windows 11 compatibility
- Added App.config with runtime switches to prevent DirectWrite crashes
- Moved software rendering initialization to App() constructor
- Disabled ReadyToRun compilation to avoid font rendering issues
- Enhanced installer with auto-launch after installation
- Removed license agreement screen from installer
- Added WiX heat.exe file harvesting for proper multi-file deployment
- Cleaned up old MSI files from repository

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 09:31:20 -08:00
cff9bc4876 Add single-instance enforcement and DirectWrite crash workaround
- Implement mutex-based single instance check
- Show message if app is already running
- Force software rendering to prevent DirectWrite font initialization crash
- Update version to 1.0.2

Fixes:
- Multiple instances could run simultaneously
- DirectWrite crash on certain Windows configurations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 08:25:36 -08:00
7 changed files with 82 additions and 8 deletions

View File

@@ -3,7 +3,7 @@
<Product Id="*" <Product Id="*"
Name="NFC Actions" Name="NFC Actions"
Language="1033" Language="1033"
Version="1.0.0.0" Version="1.0.2.0"
Manufacturer="Dangerous Things" Manufacturer="Dangerous Things"
UpgradeCode="A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D"> UpgradeCode="A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D">
@@ -20,6 +20,15 @@
<Property Id="DISABLEADVTSHORTCUTS" Value="1" /> <Property Id="DISABLEADVTSHORTCUTS" Value="1" />
<Property Id="MSIINSTALLPERUSER" Value="1" /> <Property Id="MSIINSTALLPERUSER" Value="1" />
<!-- Launch application after installation -->
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch NFC Actions" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<Property Id="WixShellExecTarget" Value="[#NfcActionsExe]" />
<CustomAction Id="LaunchApplication"
BinaryKey="WixCA"
DllEntry="WixShellExec"
Impersonate="yes" />
<Icon Id="ProductIcon" SourceFile="..\NfcActions\Resources\icon.ico" /> <Icon Id="ProductIcon" SourceFile="..\NfcActions\Resources\icon.ico" />
<Property Id="ARPPRODUCTICON" Value="ProductIcon" /> <Property Id="ARPPRODUCTICON" Value="ProductIcon" />
<Property Id="ARPHELPLINK" Value="https://dangerousthings.com" /> <Property Id="ARPHELPLINK" Value="https://dangerousthings.com" />
@@ -32,6 +41,21 @@
<ComponentRef Id="AutoStartRegistry" /> <ComponentRef Id="AutoStartRegistry" />
</Feature> </Feature>
<UI>
<!-- Use WixUI_Minimal without license page -->
<UIRef Id="WixUI_InstallDir" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<!-- Skip the license page -->
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">1</Publish>
<Publish Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder"> <Directory Id="LocalAppDataFolder">
<Directory Id="CompanyFolder" Name="DangerousThings"> <Directory Id="CompanyFolder" Name="DangerousThings">

7
NfcActions/App.config Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<!-- Force software rendering to prevent DirectWrite crashes -->
<AppContextSwitchOverrides value="Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=true;Switch.System.Windows.DoNotScaleForDpiChanges=false" />
</runtime>
</configuration>

View File

@@ -1,7 +1,9 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Media;
using NfcActions.Services; using NfcActions.Services;
using NfcActions.ViewModels; using NfcActions.ViewModels;
using Application = System.Windows.Application; using Application = System.Windows.Application;
@@ -13,6 +15,7 @@ namespace NfcActions;
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
private static Mutex? _instanceMutex;
private NotifyIcon? _notifyIcon; private NotifyIcon? _notifyIcon;
private Icon? _customIcon; private Icon? _customIcon;
private MainWindow? _mainWindow; private MainWindow? _mainWindow;
@@ -22,8 +25,40 @@ public partial class App : Application
private LogService? _logService; private LogService? _logService;
private MainViewModel? _viewModel; private MainViewModel? _viewModel;
public App()
{
// CRITICAL: Set software rendering mode BEFORE any WPF initialization
// This must be done in the constructor before InitializeComponent()
try
{
// Set environment variable as additional safeguard
Environment.SetEnvironmentVariable("DOTNET_SYSTEM_WINDOWS_DONOTUSEPRESENTATIONDPICAPABILITYTIER2ORGREATER", "1");
// Force software rendering
RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
}
catch
{
// If this fails, try to continue anyway
}
}
private void Application_Startup(object sender, StartupEventArgs e) private void Application_Startup(object sender, StartupEventArgs e)
{ {
// Ensure only one instance runs at a time
bool createdNew;
_instanceMutex = new Mutex(true, "NfcActions_SingleInstance_Mutex", out createdNew);
if (!createdNew)
{
System.Windows.MessageBox.Show("NFC Actions is already running. Check the system tray.",
"NFC Actions",
MessageBoxButton.OK,
MessageBoxImage.Information);
Shutdown();
return;
}
// Initialize services // Initialize services
_logService = new LogService(); _logService = new LogService();
_cardReaderService = new CardReaderService(_logService); _cardReaderService = new CardReaderService(_logService);
@@ -107,5 +142,7 @@ public partial class App : Application
_notifyIcon?.Dispose(); _notifyIcon?.Dispose();
_customIcon?.Dispose(); _customIcon?.Dispose();
_cardReaderService?.Dispose(); _cardReaderService?.Dispose();
_instanceMutex?.ReleaseMutex();
_instanceMutex?.Dispose();
} }
} }

View File

@@ -2,14 +2,14 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\icon.ico</ApplicationIcon> <ApplicationIcon>Resources\icon.ico</ApplicationIcon>
<Version>1.0.0</Version> <Version>1.0.2</Version>
<AssemblyVersion>1.0.0.0</AssemblyVersion> <AssemblyVersion>1.0.2.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion> <FileVersion>1.0.2.0</FileVersion>
<Company>Dangerous Things</Company> <Company>Dangerous Things</Company>
<Product>NFC Actions</Product> <Product>NFC Actions</Product>
<Description>NFC card reader monitoring and action automation</Description> <Description>NFC card reader monitoring and action automation</Description>
@@ -20,7 +20,7 @@
<PublishSingleFile>false</PublishSingleFile> <PublishSingleFile>false</PublishSingleFile>
<SelfContained>true</SelfContained> <SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishReadyToRun>true</PublishReadyToRun> <PublishReadyToRun>false</PublishReadyToRun>
<PublishTrimmed>false</PublishTrimmed> <PublishTrimmed>false</PublishTrimmed>
<EnableCompressionInSingleFile>false</EnableCompressionInSingleFile> <EnableCompressionInSingleFile>false</EnableCompressionInSingleFile>
</PropertyGroup> </PropertyGroup>

View File

@@ -9,7 +9,7 @@ param(
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path $scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$projectPath = Join-Path $scriptPath "NfcActions\NfcActions.csproj" $projectPath = Join-Path $scriptPath "NfcActions\NfcActions.csproj"
$publishPath = Join-Path $scriptPath "NfcActions\bin\Release\net7.0-windows\win-x64\publish" $publishPath = Join-Path $scriptPath "NfcActions\bin\Release\net8.0-windows\win-x64\publish"
$installerPath = Join-Path $scriptPath "Installer" $installerPath = Join-Path $scriptPath "Installer"
Write-Host "=== NFC Actions Release Build ===" -ForegroundColor Cyan Write-Host "=== NFC Actions Release Build ===" -ForegroundColor Cyan
@@ -83,6 +83,12 @@ if ($BuildInstaller) {
exit 1 exit 1
} }
# Update the harvested file to set ID to NfcActions.exe
Write-Host " Setting file ID for NfcActions.exe..." -ForegroundColor Gray
$harvestedContent = Get-Content obj\HarvestedFiles.wxs -Raw
$harvestedContent = $harvestedContent -replace '(<File Id=")([^"]+)(" KeyPath="yes" Source="\$\(var\.PublishDir\)\\NfcActions\.exe")', '$1NfcActionsExe$3'
Set-Content obj\HarvestedFiles.wxs -Value $harvestedContent
# Run candle (compile) on both wxs files # Run candle (compile) on both wxs files
Write-Host " Compiling installer..." -ForegroundColor Gray Write-Host " Compiling installer..." -ForegroundColor Gray
& candle.exe Product.wxs obj\HarvestedFiles.wxs "-dPublishDir=$publishPath" -out obj\ -arch x64 & candle.exe Product.wxs obj\HarvestedFiles.wxs "-dPublishDir=$publishPath" -out obj\ -arch x64
@@ -94,7 +100,7 @@ if ($BuildInstaller) {
# Run light (link) # Run light (link)
Write-Host " Linking MSI package..." -ForegroundColor Gray Write-Host " Linking MSI package..." -ForegroundColor Gray
& light.exe obj\Product.wixobj obj\HarvestedFiles.wixobj -out bin\NfcActions-Setup.msi -ext WixUIExtension -sval & light.exe obj\Product.wixobj obj\HarvestedFiles.wixobj -out bin\NfcActions-Setup.msi -ext WixUIExtension -ext WixUtilExtension -sval
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
Pop-Location Pop-Location
Write-Host "Light (WiX link) failed!" -ForegroundColor Red Write-Host "Light (WiX link) failed!" -ForegroundColor Red