diff --git a/windows/src/desktop/kmshell/kmshell.dproj b/windows/src/desktop/kmshell/kmshell.dproj
index c8b286254f..499f0bd9bf 100644
--- a/windows/src/desktop/kmshell/kmshell.dproj
+++ b/windows/src/desktop/kmshell/kmshell.dproj
@@ -394,18 +394,18 @@
true
-
-
- kmshell.exe
- true
-
-
.\
true
+
+
+ kmshell.exe
+ true
+
+
1
diff --git a/windows/src/desktop/kmshell/kmshell.res b/windows/src/desktop/kmshell/kmshell.res
index a4ee2686e6..b40caabf45 100644
Binary files a/windows/src/desktop/kmshell/kmshell.res and b/windows/src/desktop/kmshell/kmshell.res differ
diff --git a/windows/src/desktop/kmshell/main/UImportOlderVersionSettings.pas b/windows/src/desktop/kmshell/main/UImportOlderVersionSettings.pas
index 4cfd1992a0..44396a9f7c 100644
--- a/windows/src/desktop/kmshell/main/UImportOlderVersionSettings.pas
+++ b/windows/src/desktop/kmshell/main/UImportOlderVersionSettings.pas
@@ -24,7 +24,7 @@ unit UImportOlderVersionSettings;
interface
-function FirstRunInstallDefaults(DoDefaults,DoStartWithWindows,DoCheckForUpdates: Boolean; FDisablePackages: string): Boolean; // I2753
+function FirstRunInstallDefaults(DoDefaults,DoStartWithWindows,DoCheckForUpdates: Boolean; FDisablePackages: string; DoAutomaticallyReportUsage: Boolean): Boolean; // I2753
implementation
@@ -42,7 +42,7 @@ uses
RegistryKeys,
UImportOlderKeyboardUtils;
-function FirstRunInstallDefaults(DoDefaults,DoStartWithWindows,DoCheckForUpdates: Boolean; FDisablePackages: string): Boolean; // I2753
+function FirstRunInstallDefaults(DoDefaults,DoStartWithWindows,DoCheckForUpdates: Boolean; FDisablePackages: string; DoAutomaticallyReportUsage: Boolean): Boolean; // I2753
var
n, I: Integer;
v: Integer;
@@ -129,6 +129,8 @@ begin
if DoStartWithWindows then kmcom.Options['koStartWithWindows'].Value := True; // I2753
if DoCheckForUpdates then kmcom.Options['koCheckForUpdates'].Value := True; // I2753
+ if DoAutomaticallyReportUsage then kmcom.Options['koAutomaticallyReportUsage'].Value := True;
+
if DoDefaults then
begin
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index a1c4f58f12..8bbc5a0d6f 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -546,7 +546,8 @@ begin
Pos('installdefaults', FQuery) > 0,
Pos('startwithwindows', FQuery) > 0,
Pos('checkforupdates', FQuery) > 0,
- FDisablePackages); // I2651, I2753
+ FDisablePackages,
+ Pos('automaticallyreportusage', FQuery) > 0); // I2651, I2753
end;
UpdateAllLocaleDoctypes; // I2605
diff --git a/windows/src/desktop/kmshell/xml/locale.xml b/windows/src/desktop/kmshell/xml/locale.xml
index 0c2d02c19a..7889880678 100644
--- a/windows/src/desktop/kmshell/xml/locale.xml
+++ b/windows/src/desktop/kmshell/xml/locale.xml
@@ -2,7 +2,7 @@
-
+
Keyman
-
+
Segoe UI
9
@@ -43,7 +43,7 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
Click this icon to select a keyboard
&Name; is still running. Click this icon to use your language keyboard at any time
-
+
@@ -58,7 +58,7 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
Help
-
+
Keyboard Layouts K
Options O
@@ -94,7 +94,7 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
Languages:
✕
Add language
-
+
On Screen Keyboard:
Custom
Installed
@@ -103,7 +103,7 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
Documentation:
Installed
Not installed
-
+
Message:
Copyright:
@@ -143,6 +143,9 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
Treat hardware deadkeys as plain keys
Show hint messages
+Automatically report errors to keyman.com
+Share anonymous usage statistics with keyman.com
+
Start when Windows starts
Show splash screen
Show welcome screen
@@ -163,7 +166,7 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
User interface language...
Base Keyboard...
-
+
@@ -184,10 +187,10 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
Open Text Editor
Open Language Switcher
-
+
General Hotkeys
Keyboard Layouts
-
+
Installed Language
@@ -236,7 +239,7 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft
-
+
Install Keyboard/Package
@@ -290,22 +293,22 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to
Select Keyboards to Install
You cannot install all the keyboards in this package. You can install a maximum of %0:d additional keyboards. Please select the keyboards you wish to install from this package.
-
+
-
+
Updated &Name; Components Available
Updates for &Name_CN; are now available
Please select the updates you wish to install:
-
+
Do you want to download and install this patch now?
You can download the new version from:
Do you want to visit the website now?
-
+
Install Now
Cancel
@@ -323,7 +326,7 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to
Click this icon to download and install updates
-
+
@@ -336,12 +339,12 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to
Start Keyman
Exit
-
+
Other tasks
Configuration
Show this screen at startup
Hide this screen at startup
-
+
@@ -367,7 +370,7 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to
-
+
Language Configuration Tasks
Configure your computer to work with
@@ -429,7 +432,7 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to
-Switch &Name; &Off
+Switch &Name; &Off
On Screen &Keyboard
Keyboard &Usage
&Font Helper
@@ -441,7 +444,7 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to
E&xit
Fade When Inactive
@@ -461,7 +464,7 @@ keyboard layout for your language.
Click the buttons below to view additional documentation and/or On Screen Keyboard.
No keyboard layout is currently selected in &Name;. Click on any of the keyboard icons in the toolbar above to choose a keyboard layout.
No keyboard layouts are currently installed or loaded. Use &Name; Configuration to install a keyboard layout.
-
+
@@ -471,7 +474,7 @@ keyboard layout for your language.
&Name_CN;
@@ -483,10 +486,10 @@ keyboard layout for your language.
-A package with the name %0:s is already installed. Do you want to uninstall it and install the new one?
A keyboard with the name '%0:s' is already installed. If you continue, it will be uninstalled before the new one is installed. Continue?
@@ -502,8 +505,8 @@ keyboard layout for your language.
Codepage
Unicode
Downloading File
-
-
+
+
Are you sure you want to remove the on screen keyboard installed for %0:s?
@@ -552,7 +555,7 @@ PRIVACY WARNING: Please note that the debug logfile records all keystrokes that
Install language %0:s and link to Keyman keyboard %1:s
-
+
Please wait while &Name; finds the fonts that will work with
keyboard.
@@ -569,10 +572,10 @@ PRIVACY WARNING: Please note that the debug logfile records all keystrokes that
No fonts were found on your system that work with
. Please check the documentation to find fonts for this keyboard.
-
+
No keyboard layouts are currently installed or loaded. Use &Name; Configuration to install a keyboard layout.
Please choose a &Name; keyboard to find the fonts that will work with it.
-
+
Hint:
@@ -590,5 +593,5 @@ PRIVACY WARNING: Please note that the debug logfile records all keystrokes that
Text Editor - &Name;
-
+
diff --git a/windows/src/desktop/setup/RunTools.pas b/windows/src/desktop/setup/RunTools.pas
index 1580257aeb..9b2651b9fe 100644
--- a/windows/src/desktop/setup/RunTools.pas
+++ b/windows/src/desktop/setup/RunTools.pas
@@ -91,7 +91,9 @@ type
InstallSuccess: Boolean);
procedure CheckInstalledVersion;
function InstallMSI: Boolean;
- procedure InstallPackages(StartKeyman,StartWithWindows,CheckForUpdates,StartDisabled,StartWithConfiguration: Boolean);
+ procedure InstallPackages(StartKeyman,StartWithWindows,
+ CheckForUpdates,StartDisabled,StartWithConfiguration,
+ AutomaticallyReportUsage: Boolean);
procedure PrepareForReboot(res: Cardinal);
function RestartWindows: Boolean;
procedure RunVersion6Upgrade(const kmshellpath: WideString);
@@ -106,7 +108,9 @@ type
destructor Destroy; override;
procedure CheckInternetConnectedState;
function DownloadFile(ADownloadURL, ADownloadFilename: WideString): Boolean;
- function DoInstall(Handle: THandle; PackagesOnly, CheckForUpdatesInstall, StartAfterInstall, StartWithWindows, CheckForUpdates, StartDisabled, StartWithConfiguration: Boolean): Boolean;
+ function DoInstall(Handle: THandle; PackagesOnly, CheckForUpdatesInstall,
+ StartAfterInstall, StartWithWindows, CheckForUpdates, StartDisabled,
+ StartWithConfiguration, AutomaticallyReportUsage: Boolean): Boolean;
procedure LogError(const msg: WideString; ShowDialogIfNotSilent: Boolean = True);
property Silent: Boolean read FSilent write FSilent;
property PromptForReboot: Boolean read FPromptForReboot write FPromptForReboot; // I3355 // I3500
@@ -183,7 +187,9 @@ begin
inherited;
end;
-function TRunTools.DoInstall(Handle: THandle; PackagesOnly, CheckForUpdatesInstall, StartAfterInstall, StartWithWindows, CheckForUpdates, StartDisabled, StartWithConfiguration: Boolean): Boolean;
+function TRunTools.DoInstall(Handle: THandle; PackagesOnly, CheckForUpdatesInstall,
+ StartAfterInstall, StartWithWindows, CheckForUpdates, StartDisabled,
+ StartWithConfiguration, AutomaticallyReportUsage: Boolean): Boolean;
begin
Result := False;
@@ -211,14 +217,17 @@ begin
if InstallMSI then
begin
- InstallPackages(StartAfterInstall,StartWithWindows,CheckForUpdates,StartDisabled,StartWithConfiguration);
+ InstallPackages(StartAfterInstall,StartWithWindows,CheckForUpdates,
+ StartDisabled,StartWithConfiguration,AutomaticallyReportUsage);
Result := True;
end
end
else
begin
CheckInstalledVersion;
- InstallPackages(StartAfterInstall,StartWithWindows,CheckForUpdates,FInstallInfo.StartDisabled, FInstallInfo.StartWithConfiguration);
+ InstallPackages(StartAfterInstall,StartWithWindows,CheckForUpdates,
+ FInstallInfo.StartDisabled, FInstallInfo.StartWithConfiguration,
+ AutomaticallyReportUsage);
Result := True;
end;
end;
@@ -686,7 +695,8 @@ begin
end;
end;
-procedure TRunTools.InstallPackages(StartKeyman,StartWithWindows,CheckForUpdates,StartDisabled,StartWithConfiguration: Boolean);
+procedure TRunTools.InstallPackages(StartKeyman,StartWithWindows,CheckForUpdates,
+ StartDisabled,StartWithConfiguration,AutomaticallyReportUsage: Boolean);
var
i: Integer;
s: WideString;
@@ -715,6 +725,8 @@ begin
if StartWithWindows then s := s + 'StartWithWindows,';
if CheckForUpdates then s := s + 'CheckForUpdates,';
+ if AutomaticallyReportUsage then s := s + 'AutomaticallyReportUsage,';
+
if (FInstalledVersion.Version = '') or (FInstalledVersion.ProductCode <> FInstallerVersion.ProductCode) then s := s + 'InstallDefaults,'; // I2651
diff --git a/windows/src/desktop/setup/SetupStrings.pas b/windows/src/desktop/setup/SetupStrings.pas
index d3e3a9ba9b..43530d17b2 100644
--- a/windows/src/desktop/setup/SetupStrings.pas
+++ b/windows/src/desktop/setup/SetupStrings.pas
@@ -84,7 +84,8 @@ type
ssOptionsStartAfterInstall,
ssOptionsCheckForUpdates,
ssOptionsCheckForUpdatesBeforeInstall,
- ssOptionsUpgradeKeyboards
+ ssOptionsUpgradeKeyboards,
+ ssOptionsAutomaticallyReportUsage
);
const
@@ -155,7 +156,8 @@ const
{ssOptionsStartAfterInstall} 'Start $APPNAME when installation completes',
{ssOptionsCheckForUpdates} 'Check for updates online periodically',
{ssOptionsCheckForUpdatesBeforeInstall} 'Check for updates before installing',
- {ssOptionsUpgradeKeyboards} 'Upgrade keyboards installed with older versions to version $VERSION'
+ {ssOptionsUpgradeKeyboards} 'Upgrade keyboards installed with older versions to version $VERSION',
+ {ssOptionsAutomaticallyReportUsage} 'Share anonymous usage statistics with keyman.com'
);
implementation
diff --git a/windows/src/desktop/setup/UfrmInstallOptions.dfm b/windows/src/desktop/setup/UfrmInstallOptions.dfm
index b50708a084..d2e937641c 100644
--- a/windows/src/desktop/setup/UfrmInstallOptions.dfm
+++ b/windows/src/desktop/setup/UfrmInstallOptions.dfm
@@ -4,7 +4,7 @@ object frmInstallOptions: TfrmInstallOptions
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = 'ssOptionsTitle'
- ClientHeight = 213
+ ClientHeight = 222
ClientWidth = 505
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
@@ -59,7 +59,7 @@ object frmInstallOptions: TfrmInstallOptions
end
object cmdOK: TButton
Left = 172
- Top = 172
+ Top = 183
Width = 73
Height = 25
Caption = 'OK'
@@ -69,7 +69,7 @@ object frmInstallOptions: TfrmInstallOptions
end
object cmdCancel: TButton
Left = 260
- Top = 172
+ Top = 183
Width = 73
Height = 25
Cancel = True
@@ -77,4 +77,12 @@ object frmInstallOptions: TfrmInstallOptions
ModalResult = 2
TabOrder = 6
end
+ object chkAutomaticallyReportUsage: TCheckBox
+ Left = 16
+ Top = 153
+ Width = 473
+ Height = 17
+ Caption = 'ssOptionsAutomaticallyReportUsage'
+ TabOrder = 7
+ end
end
diff --git a/windows/src/desktop/setup/UfrmInstallOptions.pas b/windows/src/desktop/setup/UfrmInstallOptions.pas
index 3c72646cf4..121161d4c3 100644
--- a/windows/src/desktop/setup/UfrmInstallOptions.pas
+++ b/windows/src/desktop/setup/UfrmInstallOptions.pas
@@ -32,6 +32,7 @@ type
chkUpgradeKeyman7: TCheckBox;
cmdOK: TButton;
cmdCancel: TButton;
+ chkAutomaticallyReportUsage: TCheckBox;
procedure FormCreate(Sender: TObject);
private
function GetCanUpgradeKeyman7: Boolean;
@@ -46,6 +47,8 @@ type
procedure SetStartAfterInstall(const Value: Boolean);
procedure SetStartWithWindows(const Value: Boolean);
procedure SetUpgradeKeyman7(const Value: Boolean);
+ function GetAutomaticallyReportUsage: Boolean;
+ procedure SetAutomaticallyReportUsage(const Value: Boolean);
{ Private declarations }
public
{ Public declarations }
@@ -55,6 +58,7 @@ type
property CheckForUpdatesInstall: Boolean read GetCheckForUpdatesInstall write SetCheckForUpdatesInstall;
property UpgradeKeyman: Boolean read GetUpgradeKeyman7 write SetUpgradeKeyman7;
property CanUpgradeKeyman: Boolean read GetCanUpgradeKeyman7 write SetCanUpgradeKeyman7;
+ property AutomaticallyReportUsage: Boolean read GetAutomaticallyReportUsage write SetAutomaticallyReportUsage;
end;
implementation
@@ -76,6 +80,12 @@ begin
chkCheckForUpdatesInstall.Caption := FInstallInfo.Text(ssOptionsCheckForUpdatesBeforeInstall);
// Keyman 11 and later version keyboards will always automatically update
chkUpgradeKeyman7.Caption := FInstallInfo.Text(ssOptionsUpgradeKeyboards);
+ chkAutomaticallyReportUsage.Caption := FInstallInfo.Text(ssOptionsAutomaticallyReportUsage);
+end;
+
+function TfrmInstallOptions.GetAutomaticallyReportUsage: Boolean;
+begin
+ Result := chkAutomaticallyReportUsage.Checked;
end;
function TfrmInstallOptions.GetCanUpgradeKeyman7: Boolean;
@@ -108,6 +118,11 @@ begin
Result := chkUpgradeKeyman7.Checked;
end;
+procedure TfrmInstallOptions.SetAutomaticallyReportUsage(const Value: Boolean);
+begin
+ chkAutomaticallyReportUsage.Checked := Value;
+end;
+
procedure TfrmInstallOptions.SetCanUpgradeKeyman7(const Value: Boolean);
begin
chkUpgradeKeyman7.Enabled := Value;
diff --git a/windows/src/desktop/setup/UfrmRunDesktop.pas b/windows/src/desktop/setup/UfrmRunDesktop.pas
index b0f5bbc330..f5acff8d0e 100644
--- a/windows/src/desktop/setup/UfrmRunDesktop.pas
+++ b/windows/src/desktop/setup/UfrmRunDesktop.pas
@@ -91,6 +91,7 @@ type
FCheckForUpdatesInstall: Boolean;
FStartAfterInstall: Boolean;
FStartWithWindows: Boolean;
+ FAutomaticallyReportUsage: Boolean;
FDisableUpgradeFrom6Or7Or8: Boolean; // I2847 // I4293
procedure SetOfflineByRequest(const Value: Boolean);
procedure Rewrap;
@@ -494,7 +495,7 @@ begin
SetupMSI; // I2644
if GetRunTools.DoInstall(Handle, PackagesOnly, FCheckForUpdatesInstall, FStartAfterInstall, FStartWithWindows, FCheckForUpdates,
- FInstallInfo.StartDisabled, FInstallInfo.StartWithConfiguration) then
+ FInstallInfo.StartDisabled, FInstallInfo.StartWithConfiguration, FAutomaticallyReportUsage) then
begin
if not Silent and not FStartAfterInstall then // I2610
ShowMessage(FInstallInfo.Text(ssInstallSuccess));
@@ -519,6 +520,8 @@ var
oldHeight: Integer;
begin
+ FAutomaticallyReportUsage := True;
+
Application.Title := FInstallInfo.Text(ssApplicationTitle);
Caption := FInstallInfo.Text(ssTitle);
cmdInstall.Caption := FInstallInfo.Text(ssInstallButton);
@@ -599,6 +602,7 @@ procedure TfrmRunDesktop.lblOptionsClick(Sender: TObject);
begin
with TfrmInstallOptions.Create(Self) do
try
+ AutomaticallyReportUsage := FAutomaticallyReportUsage;
StartWithWindows := FStartWithWindows;
StartAfterInstall := FStartAfterInstall;
CheckForUpdates := FCheckForUpdates;
diff --git a/windows/src/developer/TIKE/dialogs/UfrmOptions.dfm b/windows/src/developer/TIKE/dialogs/UfrmOptions.dfm
index 6b59d066e5..6254b90ce4 100644
--- a/windows/src/developer/TIKE/dialogs/UfrmOptions.dfm
+++ b/windows/src/developer/TIKE/dialogs/UfrmOptions.dfm
@@ -130,6 +130,30 @@ inherited frmOptions: TfrmOptions
Caption = '&Automatically save before importing OSK'
TabOrder = 8
end
+ object gbPrivacy: TGroupBox
+ Left = 8
+ Top = 280
+ Width = 401
+ Height = 73
+ Caption = 'Privacy'
+ TabOrder = 9
+ object chkReportUsage: TCheckBox
+ Left = 8
+ Top = 44
+ Width = 311
+ Height = 17
+ Caption = '&Share anonymous usage statistics with keyman.com'
+ TabOrder = 0
+ end
+ object chkReportErrors: TCheckBox
+ Left = 8
+ Top = 21
+ Width = 311
+ Height = 17
+ Caption = 'Automatically report &errors to keyman.com'
+ TabOrder = 1
+ end
+ end
end
object tabEditor: TTabSheet
Caption = 'Editor'
diff --git a/windows/src/developer/TIKE/dialogs/UfrmOptions.pas b/windows/src/developer/TIKE/dialogs/UfrmOptions.pas
index cea5040614..f85325a33e 100644
--- a/windows/src/developer/TIKE/dialogs/UfrmOptions.pas
+++ b/windows/src/developer/TIKE/dialogs/UfrmOptions.pas
@@ -101,6 +101,9 @@ type
chkAutoSaveBeforeCompiling: TCheckBox;
chkOSKAutoSaveBeforeImporting: TCheckBox;
chkDebuggerAutoResetBeforeCompiling: TCheckBox;
+ gbPrivacy: TGroupBox;
+ chkReportUsage: TCheckBox;
+ chkReportErrors: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure cmdOKClick(Sender: TObject);
procedure cmdDefaultFontClick(Sender: TObject);
@@ -199,6 +202,9 @@ begin
editWebHostDefaultPort.Text := IntToStr(WebHostDefaultPort); // I4021
+ chkReportUsage.Checked := ReportUsage;
+ chkReportErrors.Checked := ReportErrors;
+
lblEditorCustomTheme.Caption := '';
if EditorTheme = '' then
cbEditorTheme.ItemIndex := 0
@@ -295,6 +301,9 @@ begin
ExternalEditorPath := editExternalEditorPath.Text;
DefaultProjectPath := IncludeTrailingPathDelimiter(editDefaultProjectPath.Text);
+ ReportUsage := chkReportUsage.Checked;
+ ReportErrors := chkReportErrors.Checked;
+
Write;
end;
diff --git a/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas b/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas
index 20e6fb8a50..83a85f4a79 100644
--- a/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas
+++ b/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas
@@ -62,6 +62,8 @@ type
FDebuggerAutoResetBeforeCompiling: Boolean;
FAutoSaveBeforeCompiling: Boolean;
FOSKAutoSaveBeforeImporting: Boolean;
+ FReportErrors: Boolean;
+ FReportUsage: Boolean;
procedure CloseRegistry;
procedure OpenRegistry;
function regReadString(const nm, def: string): string;
@@ -95,6 +97,9 @@ type
property AutoSaveBeforeCompiling: Boolean read FAutoSaveBeforeCompiling write FAutoSaveBeforeCompiling;
property OSKAutoSaveBeforeImporting: Boolean read FOSKAutoSaveBeforeImporting write FOSKAutoSaveBeforeImporting;
+ property ReportErrors: Boolean read FReportErrors write FReportErrors;
+ property ReportUsage: Boolean read FReportUsage write FReportUsage;
+
property WebHostDefaultPort: Integer read FWebHostDefaultPort write FWebHostDefaultPort; // I4021
property AllowMultipleInstances: Boolean read FAllowMultipleInstances write FAllowMultipleInstances;
@@ -213,6 +218,9 @@ begin
FFix183_LadderLength := regReadInt(SRegValue_IDEOpt_WebLadderLength, CRegValue_IDEOpt_WebLadderLength_Default);
FDefaultProjectPath := IncludeTrailingPathDelimiter(regReadString(SRegValue_IDEOpt_DefaultProjectPath, GetFolderPath(CSIDL_PERSONAL) + CDefaultProjectPath));
+
+ FReportErrors := regReadBool(SRegValue_AutomaticallyReportErrors, True);
+ FReportUsage := regReadBool(SRegValue_AutomaticallyReportUsage, True);
finally
CloseRegistry;
end;
@@ -257,6 +265,9 @@ begin
regWriteInt(SRegValue_IDEOpt_WebLadderLength, FFix183_LadderLength);
regWriteString(SRegValue_IDEOpt_DefaultProjectPath, FDefaultProjectPath);
+
+ regWriteBool(SRegValue_AutomaticallyReportErrors, FReportErrors);
+ regWriteBool(SRegValue_AutomaticallyReportUsage, FReportUsage);
finally
CloseRegistry;
end;
diff --git a/windows/src/developer/TIKE/main/UfrmMain.pas b/windows/src/developer/TIKE/main/UfrmMain.pas
index 7c7cc5bc52..13fe682c9b 100644
--- a/windows/src/developer/TIKE/main/UfrmMain.pas
+++ b/windows/src/developer/TIKE/main/UfrmMain.pas
@@ -430,6 +430,7 @@ uses
keymanapi_TLB,
KeymanVersion,
OnlineConstants,
+ Keyman.System.KeymanSentryClient,
Keyman.Developer.UI.TikeOnlineUpdateCheck,
GlobalProxySettings,
Keyman.Developer.System.Project.ProjectFile,
@@ -481,6 +482,8 @@ var
begin
inherited;
+ TKeymanSentryClient.Client.MessageEvent(SENTRY_LEVEL_INFO, TKeymanSentryClient.LOGGER_DEVELOPER_IDE, 'Started Keyman Developer');
+
if not ForceDirectories(FKeymanDeveloperOptions.DefaultProjectPath) then
begin
// Fall back to Documents folder if we cannot create the default project path
diff --git a/windows/src/developer/kmcomp/kmcomp.dproj b/windows/src/developer/kmcomp/kmcomp.dproj
index a8d9aa9f1f..ab8fa18e88 100644
--- a/windows/src/developer/kmcomp/kmcomp.dproj
+++ b/windows/src/developer/kmcomp/kmcomp.dproj
@@ -8,7 +8,7 @@
Console
None
18.8
- Win64
+ Win32
true
diff --git a/windows/src/engine/kmcomapi/util/utilkeymanoption.pas b/windows/src/engine/kmcomapi/util/utilkeymanoption.pas
index 973f1bd5b3..1f3a6e2718 100644
--- a/windows/src/engine/kmcomapi/util/utilkeymanoption.pas
+++ b/windows/src/engine/kmcomapi/util/utilkeymanoption.pas
@@ -121,7 +121,7 @@ type
GroupName: string;
end;
-const KeymanOptionInfo: array[0..13] of TKeymanOptionInfo = ( // I3331 // I3620 // I4552
+const KeymanOptionInfo: array[0..15] of TKeymanOptionInfo = ( // I3331 // I3620 // I4552
// Global options
(opt: koKeyboardHotkeysAreToggle; RegistryName: SRegValue_KeyboardHotkeysAreToggle; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'),
@@ -130,6 +130,9 @@ const KeymanOptionInfo: array[0..13] of TKeymanOptionInfo = ( // I3331 // I36
(opt: koShowHints; RegistryName: SRegValue_EnableHints; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'),
(opt: koBaseLayout; RegistryName: SRegValue_UnderlyingLayout; OptionType: kotLong; IntValue: 0; GroupName: 'kogGeneral'),
+ (opt: koAutomaticallyReportErrors; RegistryName: SRegValue_AutomaticallyReportErrors; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'), // I4393
+ (opt: koAutomaticallyReportUsage; RegistryName: SRegValue_AutomaticallyReportUsage; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'), // I4393
+
// OSK options
(opt: koReleaseShiftKeysAfterKeyPress; RegistryName: SRegValue_ReleaseShiftKeysAfterKeyPress; OptionType: kotBool; BoolValue: False; GroupName: 'kogOSK'),
@@ -147,7 +150,7 @@ const KeymanOptionInfo: array[0..13] of TKeymanOptionInfo = ( // I3331 // I36
(opt: koDeadkeyConversion; RegistryName: SRegValue_DeadkeyConversionMode; OptionType: kotBool; BoolValue: True; GroupName: 'kogAdvanced'), // I4552
(opt: koDebugging; RegistryName: SRegValue_KeymanDebug; OptionType: kotBool; BoolValue: False; GroupName: 'kogAdvanced') // I4393
- );
+);
implementation
diff --git a/windows/src/engine/tsysinfo/UfrmRemoteExceptionHandler.pas b/windows/src/engine/tsysinfo/UfrmRemoteExceptionHandler.pas
index d33e635696..f78c34609c 100644
--- a/windows/src/engine/tsysinfo/UfrmRemoteExceptionHandler.pas
+++ b/windows/src/engine/tsysinfo/UfrmRemoteExceptionHandler.pas
@@ -92,9 +92,11 @@ function RunCrashReportHandler: Boolean;
implementation
uses
+ System.Win.Registry,
Vcl.Clipbrd,
Keyman.System.KeymanSentryClient,
+ RegistryKeys,
Upload_Settings,
utilexecute;
@@ -118,10 +120,16 @@ const
S_Sentry_ViewEvent_URL = // Do not localize
'https://sentry.keyman.com/organizations/keyman/projects/%0:s/events/%1:s/';
+ SENTRY_PROJECT_NAME_DESKTOP = 'keyman-desktop';
+ SENTRY_PROJECT_NAME_DEVELOPER = 'keyman-developer';
+
function RunCrashReportHandler: Boolean;
var
frm: TfrmExceptionHandler;
crashID, applicationName, applicationID, projectName, eventClassName, eventMessage: string;
+ reg: TRegistry;
+ RegKey: string;
+ reportExceptions: Boolean;
begin
if ParamStr(1) <> '-c' then
Exit(False);
@@ -141,6 +149,27 @@ begin
frm.ProjectName := projectName;
frm.EventClassName := eventClassName;
frm.EventMessage := eventMessage;
+
+ // Load the registry settings for privacy settings
+
+ if projectName = SENTRY_PROJECT_NAME_DESKTOP
+ then RegKey := SRegKey_KeymanEngine_CU
+ else RegKey := SRegKey_IDEOptions_CU;
+
+ reg := TRegistry.Create;
+ try
+ reportExceptions :=
+ not reg.OpenKeyReadOnly(RegKey) or
+ not reg.ValueExists(SRegValue_AutomaticallyReportErrors) or
+ reg.ReadBool(SRegValue_AutomaticallyReportErrors);
+ finally
+ reg.Free;
+ end;
+
+ frm.lblText2.Visible := reportExceptions;
+ frm.lblNoPersonal.Visible := reportExceptions;
+ //? frm.lblNotReported.Visible := not reportExceptions;
+
frm.lblTitle.Caption := Format(S_Title_Message, [applicationName]);
Application.Run;
diff --git a/windows/src/ext/sentry/Sentry.Client.Console.pas b/windows/src/ext/sentry/Sentry.Client.Console.pas
index 8df80d3ca6..3d4817349e 100644
--- a/windows/src/ext/sentry/Sentry.Client.Console.pas
+++ b/windows/src/ext/sentry/Sentry.Client.Console.pas
@@ -8,7 +8,7 @@ uses
type
TSentryClientConsole = class(TSentryClient)
public
- constructor Create(AOptions: TSentryClientOptions; ACaptureExceptions: Boolean = True); override;
+ constructor Create(AOptions: TSentryClientOptions; AFlags: TSentryClientFlags); override;
destructor Destroy; override;
end;
@@ -17,7 +17,7 @@ implementation
{ TSentryClientConsole }
constructor TSentryClientConsole.Create(AOptions: TSentryClientOptions;
- ACaptureExceptions: Boolean);
+ AFlags: TSentryClientFlags);
begin
inherited;
diff --git a/windows/src/ext/sentry/Sentry.Client.Vcl.pas b/windows/src/ext/sentry/Sentry.Client.Vcl.pas
index 7f442c7605..2ca9efd190 100644
--- a/windows/src/ext/sentry/Sentry.Client.Vcl.pas
+++ b/windows/src/ext/sentry/Sentry.Client.Vcl.pas
@@ -11,7 +11,7 @@ type
private
procedure HandleApplicationException(Sender: TObject; E: Exception);
public
- constructor Create(AOptions: TSentryClientOptions; ACaptureExceptions: Boolean = True); override;
+ constructor Create(AOptions: TSentryClientOptions; AFlags: TSentryClientFlags); override;
destructor Destroy; override;
end;
@@ -23,11 +23,11 @@ uses
{ TSentryClientVcl }
constructor TSentryClientVcl.Create(AOptions: TSentryClientOptions;
- ACaptureExceptions: Boolean);
+ AFlags: TSentryClientFlags);
begin
- inherited Create(AOptions, ACaptureExceptions);
+ inherited Create(AOptions, AFlags);
- if ACaptureExceptions then
+ if scfCaptureExceptions in AFlags then
begin
Application.OnException := HandleApplicationException;
end;
diff --git a/windows/src/ext/sentry/Sentry.Client.pas b/windows/src/ext/sentry/Sentry.Client.pas
index 5d134445d3..d97ce2e840 100644
--- a/windows/src/ext/sentry/Sentry.Client.pas
+++ b/windows/src/ext/sentry/Sentry.Client.pas
@@ -37,6 +37,9 @@ type
TSentryClientEventType = (scetException, scetMessage);
TSentryClientEventAction = (sceaContinue, sceaTerminate);
+ TSentryClientFlag = (scfCaptureExceptions, scfReportExceptions, scfReportMessages);
+ TSentryClientFlags = set of TSentryClientFlag;
+
TSentryClientBeforeEvent = procedure(Sender: TObject; EventType: TSentryClientEventType;
event: sentry_value_t;
const EventClassName, Message: string;
@@ -54,6 +57,8 @@ type
options: psentry_options_t;
FOnBeforeEvent: TSentryClientBeforeEvent;
FOnAfterEvent: TSentryClientAfterEvent;
+ FReportExceptions: Boolean;
+ FReportMessages: Boolean;
procedure DoAfterEvent(const EventID, ExceptionClassName, Message: string;
EventType: TSentryClientEventType);
procedure DoBeforeEvent(event: sentry_value_t;
@@ -62,7 +67,7 @@ type
procedure DoTerminate;
function EventIDToString(Guid: TGUID): string;
public
- constructor Create(AOptions: TSentryClientOptions; ACaptureExceptions: Boolean = True); virtual;
+ constructor Create(AOptions: TSentryClientOptions; AFlags: TSentryClientFlags); virtual;
destructor Destroy; override;
function MessageEvent(Level: TSentryLevel; const Logger, Message: string; IncludeStack: Boolean = False): TGUID;
@@ -70,6 +75,9 @@ type
property OnBeforeEvent: TSentryClientBeforeEvent read FOnBeforeEvent write FOnBeforeEvent;
property OnAfterEvent: TSentryClientAfterEvent read FOnAfterEvent write FOnAfterEvent;
+
+ property ReportExceptions: Boolean read FReportExceptions;
+ property ReportMessages: Boolean read FReportMessages;
end;
TSentryClientClass = class of TSentryClient;
@@ -122,10 +130,12 @@ begin
end;
-constructor TSentryClient.Create(AOptions: TSentryClientOptions; ACaptureExceptions: Boolean = True);
+constructor TSentryClient.Create(AOptions: TSentryClientOptions; AFlags: TSentryClientFlags);
begin
Assert(not Assigned(FInstance));
FInstance := Self;
+ FReportExceptions := scfReportExceptions in AFlags;
+ FReportMessages := scfReportMessages in AFlags;
inherited Create;
options := sentry_options_new;
@@ -153,8 +163,7 @@ begin
sentry_init(options);
-
- if ACaptureExceptions then
+ if scfCaptureExceptions in AFlags then
begin
ExceptProc := @SentryExceptHandler;
end;
@@ -283,35 +292,43 @@ const
// A pseudo-frame is inserted at the top of the stack which points
// to the address of the code that caused the exception
begin
- event := sentry_value_new_event;
+ if FReportExceptions then
+ begin
+ event := sentry_value_new_event;
- DoBeforeEvent(event, ExceptionClassName, Message, scetException);
+ DoBeforeEvent(event, ExceptionClassName, Message, scetException);
-(*
- When we set exception information, the report is corrupted. Not sure why. So
- for now we won't create as an exception event. We still get all the information
- we want from this.
+ (*
+ When we set exception information, the report is corrupted. Not sure why. So
+ for now we won't create as an exception event. We still get all the information
+ we want from this.
- Investigating this further at https://forum.sentry.io/t/corrupted-display-when-exception-data-is-set-using-native-sdk/9167/2
+ Investigating this further at https://forum.sentry.io/t/corrupted-display-when-exception-data-is-set-using-native-sdk/9167/2
- exc := sentry_value_new_object;
- sentry_value_set_by_key(exc, 'type', sentry_value_new_string(PAnsiChar(UTF8Encode(ExceptionClassName))));
- sentry_value_set_by_key(exc, 'value', sentry_value_new_string(PAnsiChar(UTF8Encode(Message))));
- sentry_value_set_by_key(event, 'exception', exc);
-*)
+ exc := sentry_value_new_object;
+ sentry_value_set_by_key(exc, 'type', sentry_value_new_string(PAnsiChar(UTF8Encode(ExceptionClassName))));
+ sentry_value_set_by_key(exc, 'value', sentry_value_new_string(PAnsiChar(UTF8Encode(Message))));
+ sentry_value_set_by_key(event, 'exception', exc);
+ *)
- sentry_value_set_by_key(event, 'message', sentry_value_new_string(PAnsiChar(UTF8Encode(Message))));
+ sentry_value_set_by_key(event, 'message', sentry_value_new_string(PAnsiChar(UTF8Encode(Message))));
- if AExceptAddr = nil then
- AExceptAddr := System.ExceptAddr;
- threads := CaptureStackTrace(AExceptAddr, FRAMES_TO_SKIP);
- if threads <> 0 then
- sentry_value_set_by_key(event, 'threads', threads);
+ if AExceptAddr = nil then
+ AExceptAddr := System.ExceptAddr;
+ threads := CaptureStackTrace(AExceptAddr, FRAMES_TO_SKIP);
+ if threads <> 0 then
+ sentry_value_set_by_key(event, 'threads', threads);
- uuid := sentry_capture_event(event);
- Result := uuid.native_uuid;
+ uuid := sentry_capture_event(event);
+ Result := uuid.native_uuid;
- DoAfterEvent(EventIDToString(Result), ExceptionClassName, Message, scetException);
+ DoAfterEvent(EventIDToString(Result), ExceptionClassName, Message, scetException);
+ end
+ else
+ begin
+ DoBeforeEvent(0, ExceptionClassName, Message, scetException);
+ DoAfterEvent('', ExceptionClassName, Message, scetException);
+ end;
end;
function TSentryClient.MessageEvent(Level: TSentryLevel; const Logger,
@@ -325,24 +342,32 @@ const
// Sentry.Client.CaptureStackTrace,
// Sentry.Client.TSentryClient.MessageEvent
begin
- event := sentry_value_new_message_event(
- {* level *} sentry_level_t(Level),
- {* logger *} PAnsiChar(UTF8Encode(Logger)),
- {* message *} PAnsiChar(UTF8Encode(Message))
- );
-
- DoBeforeEvent(event, Logger, Message, scetMessage);
-
- if IncludeStack then
+ if FReportMessages or (FReportExceptions and (Level in [SENTRY_LEVEL_ERROR, SENTRY_LEVEL_FATAL])) then
begin
- threads := CaptureStackTrace(nil, FRAMES_TO_SKIP);
- if threads <> 0 then
- sentry_value_set_by_key(event, 'threads', threads);
+ event := sentry_value_new_message_event(
+ {* level *} sentry_level_t(Level),
+ {* logger *} PAnsiChar(UTF8Encode(Logger)),
+ {* message *} PAnsiChar(UTF8Encode(Message))
+ );
+
+ DoBeforeEvent(event, Logger, Message, scetMessage);
+
+ if IncludeStack then
+ begin
+ threads := CaptureStackTrace(nil, FRAMES_TO_SKIP);
+ if threads <> 0 then
+ sentry_value_set_by_key(event, 'threads', threads);
+ end;
+
+ Result := sentry_capture_event(event).native_uuid;
+
+ DoAfterEvent(EventIDToString(Result), Logger, Message, scetMessage);
+ end
+ else
+ begin
+ DoBeforeEvent(0, Logger, Message, scetMessage);
+ DoAfterEvent('', Logger, Message, scetMessage);
end;
-
- Result := sentry_capture_event(event).native_uuid;
-
- DoAfterEvent(EventIDToString(Result), Logger, Message, scetMessage);
end;
end.
diff --git a/windows/src/global/delphi/general/Keyman.System.KeymanSentryClient.pas b/windows/src/global/delphi/general/Keyman.System.KeymanSentryClient.pas
index 21e139e3b8..a0e52cd55f 100644
--- a/windows/src/global/delphi/general/Keyman.System.KeymanSentryClient.pas
+++ b/windows/src/global/delphi/general/Keyman.System.KeymanSentryClient.pas
@@ -26,6 +26,8 @@ type
class procedure Stop;
class property Client: TSentryClient read FClient;
class property Instance: TKeymanSentryClient read FInstance;
+ public
+ const LOGGER_DEVELOPER_IDE = 'KeymanDeveloper.IDE';
end;
@@ -36,6 +38,7 @@ uses
System.Generics.Collections,
System.JSON,
System.SysUtils,
+ System.Win.Registry,
{$IF NOT DEFINED(CONSOLE)}
System.UITypes,
Vcl.Dialogs,
@@ -46,6 +49,7 @@ uses
KeymanPaths,
KeymanVersion,
+ RegistryKeys,
utilexecute;
const
@@ -95,14 +99,16 @@ begin
if EventType = scetException then
begin
// We need to look for a kmcomapi errlog and report that
- ReportRemoteErrors(EventID);
+ if FClient.ReportExceptions then
+ ReportRemoteErrors(EventID);
if kscfShowUI in FFlags then
begin
{$IF DEFINED(CONSOLE)}
// Write to console
writeln(ErrOutput, 'Fatal error '+EventClassName+': '+Message);
- writeln(ErrOutput, 'This error has been automatically reported to the Keyman team.');
+ if FClient.ReportExceptions then
+ writeln(ErrOutput, 'This error has been automatically reported to the Keyman team.');
writeln(ErrOutput);
{$ELSE}
// Launch external gui exception dialog app.
@@ -215,7 +221,10 @@ end;
constructor TKeymanSentryClient.Create(SentryClientClass: TSentryClientClass; AProject: TKeymanSentryClientProject; AFlags: TKeymanSentryClientFlags);
var
+ reg: TRegistry;
o: TSentryClientOptions;
+ f: TSentryClientFlags;
+ RegKey: string;
begin
Assert(not Assigned(FInstance));
@@ -235,7 +244,37 @@ begin
o.Release := 'release-'+CKeymanVersionInfo.VersionWithTag;
- FClient := SentryClientClass.Create(o, kscfCaptureExceptions in FFlags);
+ if kscfCaptureExceptions in FFlags
+ then f := [scfCaptureExceptions]
+ else f := [];
+
+ // Load the registry settings for privacy settings
+
+ if AProject = kscpDesktop
+ then RegKey := SRegKey_KeymanEngine_CU
+ else RegKey := SRegKey_IDEOptions_CU;
+
+ reg := TRegistry.Create;
+ try
+ if reg.OpenKeyReadOnly(RegKey) then
+ begin
+ if not reg.ValueExists(SRegValue_AutomaticallyReportErrors) or
+ reg.ReadBool(SRegValue_AutomaticallyReportErrors) then
+ Include(f, scfReportExceptions);
+ if not reg.ValueExists(SRegValue_AutomaticallyReportUsage) or
+ reg.ReadBool(SRegValue_AutomaticallyReportUsage) then
+ Include(f, scfReportMessages);
+ end
+ else
+ begin
+ Include(f, scfReportExceptions);
+ Include(f, scfReportMessages);
+ end;
+ finally
+ reg.Free;
+ end;
+
+ FClient := SentryClientClass.Create(o, f);
FClient.OnAfterEvent := ClientAfterEvent;
end;
diff --git a/windows/src/global/delphi/general/KeymanOptionNames.pas b/windows/src/global/delphi/general/KeymanOptionNames.pas
index 8097a968a5..27aef82ab5 100644
--- a/windows/src/global/delphi/general/KeymanOptionNames.pas
+++ b/windows/src/global/delphi/general/KeymanOptionNames.pas
@@ -20,7 +20,9 @@ type
koAutoOpenOSK, // I1288
koAutoSwitchOSKPages, // I1375
koUseTouchLayout,
- koBaseLayout
+ koBaseLayout,
+ koAutomaticallyReportErrors,
+ koAutomaticallyReportUsage
);
function KeymanOptionName(Option: TUtilKeymanOption): string;
diff --git a/windows/src/global/delphi/general/RegistryKeys.pas b/windows/src/global/delphi/general/RegistryKeys.pas
index 6d775b8fe0..3d32a5acc3 100644
--- a/windows/src/global/delphi/general/RegistryKeys.pas
+++ b/windows/src/global/delphi/general/RegistryKeys.pas
@@ -183,6 +183,11 @@ const
SRegValue_AvailableLanguages = 'available languages'; //CU
SRegValue_CurrentLanguage = 'current language'; //CU
+ { Privacy }
+
+ SRegValue_AutomaticallyReportErrors = 'automatically report errors'; // CU, SRegKey_IDEOptions and SRegKey_KeymanEngine_CU
+ SRegValue_AutomaticallyReportUsage = 'automatically report usage'; // CU, SRegKey_IDEOptions and SRegKey_KeymanEngine_CU
+
{ ActiveKeyboards }
SRegKey_ActiveKeyboards_CU = SRegKey_KeymanEngine_CU + '\Active Keyboards'; // CU
diff --git a/windows/src/global/inc/registry.h b/windows/src/global/inc/registry.h
index 33c6b3441f..ea61282e67 100644
--- a/windows/src/global/inc/registry.h
+++ b/windows/src/global/inc/registry.h
@@ -126,6 +126,13 @@
#define REGSZ_DeepTSFIntegration "deep tsf integration"
+/* Privacy settings - all DWORD 0/1 */
+
+#define REGSZ_IDEOptions_CU ( REGSZ_KeymanDeveloperCU "\\IDE\\Options" )
+
+#define REGSZ_AutomaticallyReportErrors "automatically report errors" // CU, SRegKey_IDEOptions and SRegKey_KeymanEngine_CU
+#define REGSZ_AutomaticallyReportUsage "automatically report usage" // CU, SRegKey_IDEOptions and SRegKey_KeymanEngine_CU
+
/* Splitting Registry into ReadOnly and FullAccess makes it much easier to ensure that we are using the registry
correctly -- readonly wherever possible. */
diff --git a/windows/src/global/vc/keymansentry.cpp b/windows/src/global/vc/keymansentry.cpp
index ea22efb05d..28e0cedc2c 100644
--- a/windows/src/global/vc/keymansentry.cpp
+++ b/windows/src/global/vc/keymansentry.cpp
@@ -3,17 +3,41 @@
#include
#include
#include
+#include
#define SENTRY_DSN_DESKTOP "https://92eb58e6005d47daa33c9c9e39458eb7@sentry.keyman.com/5"
#define SENTRY_DSN_DEVELOPER "https://39b25a09410349a58fe12aaf721565af@sentry.keyman.com/6"
+bool g_report_exceptions, g_report_messages;
+
int keyman_sentry_init(bool is_keyman_developer) {
sentry_options_t *options = sentry_options_new();
+ const char *key;
if (is_keyman_developer) {
sentry_options_set_dsn(options, SENTRY_DSN_DEVELOPER);
+ key = REGSZ_IDEOptions_CU;
} else {
sentry_options_set_dsn(options, SENTRY_DSN_DESKTOP);
+ key = REGSZ_KeymanCU;
+ }
+
+ HKEY hkey;
+ if (RegOpenKeyExA(HKEY_CURRENT_USER, key, 0, KEY_READ, &hkey) == ERROR_SUCCESS) {
+ DWORD dwType, dwValue, dwValueSize = 4;
+
+ g_report_exceptions =
+ RegQueryValueExA(hkey, REGSZ_AutomaticallyReportErrors, NULL, &dwType, (LPBYTE)&dwValue, &dwValueSize) != ERROR_SUCCESS || dwType != REG_DWORD || dwValue != 0;
+
+ dwValueSize = 4;
+ g_report_messages =
+ RegQueryValueExA(hkey, REGSZ_AutomaticallyReportUsage, NULL, &dwType, (LPBYTE)&dwValue, &dwValueSize) != ERROR_SUCCESS || dwType != REG_DWORD || dwValue != 0;
+
+ RegCloseKey(hkey);
+ }
+ else {
+ g_report_exceptions = true;
+ g_report_messages = true;
}
sentry_options_set_release(options, KEYMAN_VersionWithTag);
@@ -76,56 +100,60 @@ void keyman_sentry_report_exception(DWORD ExceptionCode, PVOID ExceptionAddress)
sentry_value_t event;
const int FRAMES_TO_SKIP = 0;
- event = sentry_value_new_event();
+ if (g_report_exceptions) {
+ event = sentry_value_new_event();
- char message[64];
- wsprintfA(message, "Exception %x at %p", ExceptionCode, ExceptionAddress);
+ char message[64];
+ wsprintfA(message, "Exception %x at %p", ExceptionCode, ExceptionAddress);
- /*
- When we set exception information, the report is corrupted. Not sure why. So
- for now we won't create as an exception event. We still get all the information
- we want from this.
+ /*
+ When we set exception information, the report is corrupted. Not sure why. So
+ for now we won't create as an exception event. We still get all the information
+ we want from this.
- Investigating this further at https://forum.sentry.io/t/corrupted-display-when-exception-data-is-set-using-native-sdk/9167/2
+ Investigating this further at https://forum.sentry.io/t/corrupted-display-when-exception-data-is-set-using-native-sdk/9167/2
- sentry_value_t exc = sentry_value_new_object();
- sentry_value_set_by_key(exc, "type", sentry_value_new_string("Exception"));
- sentry_value_set_by_key(exc, "value", sentry_value_new_string(message));
- sentry_value_set_by_key(event, "exception", exc);*/
- sentry_value_set_by_key(event, "message", sentry_value_new_string(message));
+ sentry_value_t exc = sentry_value_new_object();
+ sentry_value_set_by_key(exc, "type", sentry_value_new_string("Exception"));
+ sentry_value_set_by_key(exc, "value", sentry_value_new_string(message));
+ sentry_value_set_by_key(event, "exception", exc);*/
+ sentry_value_set_by_key(event, "message", sentry_value_new_string(message));
- //sentry_event_value_add_stacktrace(event, &ExceptionAddress, 64);
- sentry_value_t threads = CaptureStackTrace(ExceptionAddress, FRAMES_TO_SKIP);
- if (threads._bits != 0) {
- sentry_value_set_by_key(event, "threads", threads);
+ //sentry_event_value_add_stacktrace(event, &ExceptionAddress, 64);
+ sentry_value_t threads = CaptureStackTrace(ExceptionAddress, FRAMES_TO_SKIP);
+ if (threads._bits != 0) {
+ sentry_value_set_by_key(event, "threads", threads);
+ }
+
+ sentry_capture_event(event);
+
+ perror(message);
}
-
- sentry_capture_event(event);
-
- perror(message);
}
void keyman_sentry_report_message(keyman_sentry_level_t level, const char *logger, const char *message, bool includeStack) {
const int FRAMES_TO_SKIP = 0;
- sentry_value_t event;
+ if ((g_report_exceptions && (level == SENTRY_LEVEL_ERROR || level == SENTRY_LEVEL_DEBUG)) || g_report_messages) {
+ sentry_value_t event;
- event = sentry_value_new_event();
+ event = sentry_value_new_event();
- event = sentry_value_new_message_event(
- /*level */ sentry_level_t(level),
- /*logger */ logger,
- /*message*/ message
- );
+ event = sentry_value_new_message_event(
+ /*level */ sentry_level_t(level),
+ /*logger */ logger,
+ /*message*/ message
+ );
- if (includeStack) {
- sentry_value_t threads = CaptureStackTrace(NULL, FRAMES_TO_SKIP);
- if (threads._bits != 0) {
- sentry_value_set_by_key(event, "threads", threads);
+ if (includeStack) {
+ sentry_value_t threads = CaptureStackTrace(NULL, FRAMES_TO_SKIP);
+ if (threads._bits != 0) {
+ sentry_value_set_by_key(event, "threads", threads);
+ }
}
- }
- sentry_capture_event(event);
+ sentry_capture_event(event);
+ }
}
/* Wrappers for main, wmain */