Window Logger is a productivity tracking tool that monitors active windows and analyzes time spent across applications and categories. The system consists of two .NET console applications that work together to provide insights into computer usage patterns.
The system has two main components:
- WindowLogger - Monitors and logs active windows continuously
- WindowAnalyser - Analyzes logs and generates Excel reports
Build both applications using Visual Studio or the .NET CLI:
# From the solution directory
dotnet build WindowLogger.slnOr build individual projects:
dotnet build WindowLogger/WindowLogger.csproj
dotnet build WindowAnalyser/WindowAnalyser.csprojNavigate to the WindowLogger output directory and run:
cd WindowLogger/bin/Debug/net9.0
WindowLogger.exeOr from the project directory:
cd WindowLogger
dotnet runWhat happens:
- The logger starts monitoring your active windows every 100ms
- Console displays each window change
- Data is saved to
window_log.csvin the same directory as the executable - Press Enter to stop logging
Navigate to the WindowAnalyser output directory and run:
cd WindowAnalyser/bin/Debug/net9.0
WindowAnalyser.exe window_log.csv output.xlsxOr from the project directory:
cd WindowAnalyser
dotnet run -- <path-to-csv> <output-xlsx-path>Example:
dotnet run -- ../../WindowLogger/bin/Debug/net9.0/window_log.csv weekly_report.xlsxFile Name: window_log.csv
Location: Same directory as WindowLogger.exe
When running with dotnet run, the log file is created in:
WindowLogger/bin/Debug/net9.0/window_log.csvWhen running the compiled executable directly:
<path-to-exe>/window_log.csvThe CSV file contains three columns:
Timestamp,Window Title [Executable],Status
Example Content:
2026-01-18 09:15:30,Visual Studio 2022 [devenv.exe],Active
2026-01-18 09:20:45,Google Chrome - GitHub [chrome.exe],Active
2026-01-18 09:25:10,Slack - Development Team [slack.exe],Active
2026-01-18 09:30:00,Slack - Development Team [slack.exe],Inactive
2026-01-18 09:31:15,Visual Studio 2022 [devenv.exe],ActiveStatus Values:
Active- User is actively using the computerInactive- No user input detected for 1+ minute (configurable)
File Name: appsettings.json
Location: Same directory as WindowAnalyser.exe
The configuration file must be in:
WindowAnalyser/bin/Debug/net9.0/appsettings.json
The project is already configured to copy this file to the output directory automatically.
- Real-time Window Tracking: Monitors the foreground window every 100ms
- Executable Detection: Records both window title and process name
- Inactivity Detection: Automatically detects when user is idle (default: 1 minute)
- Continuous Logging: Appends to CSV file - safe to stop/restart
- Polls the foreground window every 100 milliseconds
- Detects window changes and logs them with timestamp
- Monitors user input (keyboard/mouse) to detect inactivity
- When inactive for 1 minute, logs "Inactive" status
- When activity resumes, logs "Active" status with new window
Edit constants in WindowLogger/Program.cs:
private const double MinutesToInactive = 1; // Inactivity threshold in minutesChange timer interval (default: 100ms):
_timer = new Timer(100); // Polling interval in millisecondsOption 1: Start Minimized
- Create a shortcut to
WindowLogger.exe - Right-click → Properties → Run: Minimized
Option 2: Windows Task Scheduler
- Schedule to run at login
- Run whether user is logged on or not
- Configure to restart on failure
WindowAnalyser.exe <input-csv-file> <output-xlsx-file>Parameters:
input-csv-file- Path to the CSV log file created by WindowLoggeroutput-xlsx-file- Desired path/name for the Excel report
Examples:
# Absolute paths
WindowAnalyser.exe C:\Logs\window_log.csv C:\Reports\weekly_report.xlsx
# Relative paths
WindowAnalyser.exe window_log.csv report.xlsx
# Analyze multiple periods
WindowAnalyser.exe logs\january.csv reports\january_analysis.xlsx
WindowAnalyser.exe logs\february.csv reports\february_analysis.xlsxThe output workbook contains 4 worksheets:
Groups time by configured categories (e.g., "Productivity", "Development")
| Category | Status | Time Spent (Minutes) | Time Spent (Hours) |
|---|---|---|---|
| Development | Active | 240.5 | 4.01 |
| Communication | Active | 95.2 | 1.59 |
| Productivity | Inactive | 15.0 | 0.25 |
Groups time by configured application names
| Application | Status | Time Spent (Minutes) | Time Spent (Hours) |
|---|---|---|---|
| Visual Studio | Active | 180.3 | 3.01 |
| Browser | Active | 120.5 | 2.01 |
| Slack | Active | 45.2 | 0.75 |
Shows windows that didn't match any application rule - use this to identify applications you should add to your configuration
| Window | Status | Time Spent (Minutes) | Time Spent (Hours) |
|---|---|---|---|
| Calculator [calc.exe] | Active | 25.5 | 0.43 |
| Notepad++ [notepad++.exe] | Active | 18.2 | 0.30 |
Daily breakdown of all window activity
| Date | Window | Status | Time Spent (Minutes) | Time Spent (Hours) |
|---|---|---|---|---|
| 2026-01-18 | Visual Studio | Active | 120.5 | 2.01 |
| 2026-01-18 | Chrome | Active | 65.3 | 1.09 |
| 2026-01-19 | Visual Studio | Active | 180.0 | 3.00 |
-
First Run - Without
appsettings.jsonWindowAnalyser.exe window_log.csv initial_report.xlsx
- All windows appear in "Undefined Applications" tab
- No categories are generated
-
Review Undefined Applications
- Open the Excel report
- Check the "Undefined Applications" tab
- Identify which windows you want to track
-
Configure Application Rules
- Edit
appsettings.jsonin the WindowAnalyser directory - Add application definitions based on window titles
- Define categories for grouping
- Edit
-
Re-run Analysis
WindowAnalyser.exe window_log.csv categorized_report.xlsx
- Applications now appear in "Applications" tab
- Categories are populated
- "Undefined Applications" shows only unmatched windows
-
Iterate
- Continue refining rules until most windows are categorized
- Run analysis periodically (daily/weekly) to track trends
The appsettings.json file controls how window titles are classified.
{
"applications": [ ... ],
"exclusions": [ ... ],
"categories": [ ... ]
}Define how window titles map to logical application names.
Properties:
name- Logical application name (appears in report)include- Keywords that must all appear in the window titleexclude- Keywords that must not appear (optional)
Example:
{
"name": "Browser",
"include": [ "Firefox" ],
"exclude": [ "taskbeat" ]
}Matching Rules:
- All
includekeywords must be present (AND logic) - Any
excludekeyword disqualifies the match - Matching is case-insensitive
- First match wins - order matters!
Best Practices:
- Specific rules first, generic rules last:
{
"applications": [
{
"name": "Notepad - MyTask",
"include": [ "Notepad", "MyTask.txt" ],
"exclude": []
},
{
"name": "Notepad",
"include": [ "Notepad" ],
"exclude": [ "MyTask.txt" ]
}
]
}- Use executable names for precision:
{
"name": "Visual Studio",
"include": [ "Visual Studio", "devenv.exe" ],
"exclude": []
}- Group similar browsers:
[
{
"name": "Browser",
"include": [ "Firefox" ],
"exclude": []
},
{
"name": "Browser",
"include": [ "Chrome" ],
"exclude": []
},
{
"name": "Browser",
"include": [ "Edge" ],
"exclude": []
}
]Define window titles to completely remove from analysis.
Example:
{
"exclusions": [
{
"include": [ "Firefox", "ebay", "cart" ]
},
{
"include": [ "private", "browsing" ]
}
]
}When a window matches an exclusion rule:
- It's removed from all reports
- Time is not counted anywhere
- It's as if the window never existed
Use Cases:
- Exclude personal browsing during work hours
- Filter out sensitive/private windows
- Remove testing/debugging windows
Group applications into higher-level categories for aggregate reporting.
Properties:
name- Category name (appears in report)includeApplications- Application names to includeexcludeApplications- Applications to exclude (optional)
Example:
{
"categories": [
{
"name": "Development",
"includeApplications": [ "Visual Studio", "VS Code", "Terminal" ],
"excludeApplications": []
},
{
"name": "Productivity",
"includeApplications": [ "Notepad", "TaskBeat" ],
"excludeApplications": [ "Notepad - MyTask" ]
},
{
"name": "Communication",
"includeApplications": [ "Slack", "Teams", "Outlook" ],
"excludeApplications": []
}
]
}Important:
- Applications can belong to multiple categories
- Time is counted separately for each category (can exceed 100%)
- Use
excludeApplicationsto create exceptions within broader groups
{
"applications": [
{
"name": "Visual Studio",
"include": [ "Visual Studio" ],
"exclude": []
},
{
"name": "VS Code",
"include": [ "Visual Studio Code" ],
"exclude": []
},
{
"name": "Browser",
"include": [ "Firefox" ],
"exclude": [ "taskbeat" ]
},
{
"name": "TaskBeat",
"include": [ "Firefox", "taskbeat" ],
"exclude": []
},
{
"name": "Slack",
"include": [ "Slack" ],
"exclude": []
},
{
"name": "Notepad - MyTask",
"include": [ "Notepad", "MyTask.txt" ],
"exclude": []
},
{
"name": "Notepad",
"include": [ "Notepad" ],
"exclude": [ "MyTask.txt" ]
}
],
"exclusions": [
{
"include": [ "Firefox", "ebay", "cart" ]
}
],
"categories": [
{
"name": "Development",
"includeApplications": [ "Visual Studio", "VS Code" ],
"excludeApplications": []
},
{
"name": "Communication",
"includeApplications": [ "Slack" ],
"excludeApplications": []
},
{
"name": "Productivity",
"includeApplications": [ "Notepad", "TaskBeat" ],
"excludeApplications": [ "Notepad - MyTask" ]
},
{
"name": "MyTask",
"includeApplications": [ "Notepad - MyTask" ],
"excludeApplications": []
}
]
}- Operating System: Windows (uses Win32 APIs for window tracking)
- .NET Runtime: .NET 9.0 or higher
- Excel Viewer: Microsoft Excel or compatible spreadsheet application
WindowLogger:
- No external dependencies (uses built-in Windows APIs)
WindowAnalyser:
- ClosedXML (0.105.0-rc) - for Excel generation
- Newtonsoft.Json (13.0.3) - for configuration parsing
- Run Continuously: Leave WindowLogger running all day for accurate tracking
- Regular Analysis: Analyze logs daily or weekly to identify patterns
- Backup Logs: Copy CSV files regularly - they contain your complete history
- Multiple Logs: Create separate logs for different projects or time periods by moving/renaming the CSV file
- Start Simple: Begin with broad application categories
- Refine Gradually: Add more specific rules as you identify patterns
- Use Undefined Tab: Regularly check "Undefined Applications" to find unmatched windows
- Test Rules: Re-run analysis after configuration changes to verify rules work as expected
- Document Rules: Add comments (not supported in JSON, but keep notes separately) about why specific rules exist
- Compare Periods: Generate reports for different time periods to track changes
- Focus on Active Time: Filter by "Active" status to see productive time
- Review Inactive Patterns: High inactive time may indicate distractions or away-from-desk time
- Category Overlaps: Remember that categories can overlap - total category time may exceed 100%
Cause: Configuration file is missing or has invalid JSON
Solution:
- Ensure
appsettings.jsonexists in the same directory asWindowAnalyser.exe - Validate JSON syntax using a JSON validator
- The analyzer will use default settings (no grouping) if the file is invalid
Cause: Log file is corrupted or has an unexpected format
Solution:
- Check that the CSV file was created by WindowLogger
- Ensure the file hasn't been manually edited with incorrect formatting
- Verify the file isn't empty
Cause: No windows matched your application rules
Solution:
- Check the "Undefined Applications" tab to see what windows were logged
- Add application rules to
appsettings.jsonmatching those window titles - Re-run the analysis
Cause: Running continuously for extended periods
Solution:
- Archive old logs regularly (e.g., monthly)
- Analyze and move the CSV file to a different location
- WindowLogger will create a new
window_log.csvautomatically
This project is open source and available under the repository license.