Skip to content

Commit

Permalink
Moved the logs directory from %USERPROFILE%\ShellAnything\Logs to `…
Browse files Browse the repository at this point in the history
…%LOCALAPPDATA%\ShellAnything\logs`. #108
  • Loading branch information
end2endzone committed Oct 27, 2024
1 parent 84140ab commit 0513e63
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 20 deletions.
4 changes: 3 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
Changes for 0.10.0

* **Breaking change:** The _Configuration Files_ directory has moved from `%USERPROFILE%\ShellAnything` to `%USERPROFILE%\ShellAnything\configurations`. On first application launch, Configuration Files in the old directory will move to the new directory automatically. Other files in `%USERPROFILE%\ShellAnything` will not be moved.
* **Breaking change:** The _Configuration Files_ directory has moved from `%USERPROFILE%\ShellAnything` to `%USERPROFILE%\ShellAnything\configurations`. Configuration Files in the old directory will move to the new directory automatically on application first launch. Other files in `%USERPROFILE%\ShellAnything` will not be moved.
* **Breaking change:** The _logs_ directory has moved from `%USERPROFILE%\ShellAnything\Logs` to `%LOCALAPPDATA%\ShellAnything\logs`. The previous logs directory will be removed on application first launch.
* ShellAnything has a new high-resolution logo icon!
* Shellanything now features verbose logging mode and command line arguments debugging tools.
* ShellAnything now packages icons from [icons8/flat-color-icons](https://github.com/icons8/flat-color-icons).

Fixes:
* Fixed issue #6 : (twice) Right-click on a directory with Windows Explorer in the left panel shows the menus twice.
* Fixed issue #31 : (twice) Error in logs for CContextMenu::GetCommandString()
* Fixed issue #108: Separate location for log files ? (and exclusions?)
* Fixed issue #109: Implement default and verbose logging.
* Fixed issue #110: Create a simple command line arguments debugging application.
* Fixed issue #148: Can't uninstall.
Expand Down
4 changes: 1 addition & 3 deletions UserManual.md
Original file line number Diff line number Diff line change
Expand Up @@ -2651,9 +2651,7 @@ ShellAnything provides logging support for troubleshooting and debugging command

The logging directory is unique for each users of the system.

The log files are stored in `C:\Users\%USERNAME%\ShellAnything\Logs` directory where `%USERNAME%` matches your current login username.
For example, the user `JohnSmith` can find his own ShellAnything log files in directory `C:\Users\JohnSmith\ShellAnything\Logs`.

The log files are stored in `%LOCALAPPDATA%\ShellAnything\logs` directory. For example, the user `JohnSmith` can find his own ShellAnything log files in directory `C:\Users\JohnSmith\AppData\Local\ShellAnything\logs`.


### Filename Format ###
Expand Down
93 changes: 79 additions & 14 deletions src/core/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ namespace shellanything
return false;
}

std::string App::GetLegacyLogsDirectory()
{
//get home directory of the user
std::string home_dir = ra::user::GetHomeDirectoryUtf8();
std::string legacy_dir = home_dir + "\\" + app_name + "\\Logs";
return legacy_dir;
}

std::string App::GetLogDirectory()
{
//Issue #10 - Change the log directory if run from the unit tests executable
Expand Down Expand Up @@ -195,21 +203,30 @@ namespace shellanything
//This DLL is most probably executed by the shell (File Explorer).

//By default, GLOG will output log files in %TEMP% directory.
//However, I prefer to use %USERPROFILE%\ShellAnything\logs
std::string log_dir = ra::user::GetHomeDirectoryUtf8();
if (!log_dir.empty())

// Issue #108. Log files should be stored in %LOCALAPPDATA%\ShellAnything\logs
std::string localappdata_dir = ra::environment::GetEnvironmentVariableUtf8("LOCALAPPDATA");
if (!localappdata_dir.empty() && ra::filesystem::DirectoryExistsUtf8(localappdata_dir.c_str()))
{
std::string log_dir = localappdata_dir + "\\" + app_name + "\\logs";
if (IsValidLogDirectory(log_dir))
return log_dir;
}

// Fallback to %USERPROFILE%\ShellAnything\logs
std::string home_dir = ra::user::GetHomeDirectoryUtf8();
if (!home_dir.empty() && ra::filesystem::DirectoryExistsUtf8(home_dir.c_str()))
{
//We got the %USERPROFILE% directory.
//Now add our custom path to it
log_dir.append("\\" + app_name + "\\logs");
std::string log_dir = home_dir + "\\" + app_name + "\\logs";
if (IsValidLogDirectory(log_dir))
return log_dir;
}

//Failed getting HOME directory.
//Fallback to using %TEMP%.
log_dir = ra::environment::GetEnvironmentVariableUtf8("TEMP");
return log_dir;
std::string temp_dir = ra::environment::GetEnvironmentVariableUtf8("TEMP");
return temp_dir;
}

std::string App::GetLegacyConfigurationsDirectory()
Expand Down Expand Up @@ -329,16 +346,17 @@ namespace shellanything
}
}

void App::ClearLegacyConfigurationDirectory(const std::string& legacy_dir)
void App::ClearLegacyConfigurationDirectory()
{
const std::string legacy_config_dir = GetLegacyConfigurationsDirectory();
const std::string config_dir = GetConfigurationsDirectory();
if (legacy_dir == config_dir)
if (legacy_config_dir == config_dir)
return; // nothing to do

// Search for xml files directly under legacy_dir
ra::strings::StringVector files;
static const int depth = 0; // Do not search recursively
bool success = ra::filesystem::FindFilesUtf8(files, legacy_dir.c_str(), depth);
bool success = ra::filesystem::FindFilesUtf8(files, legacy_config_dir.c_str(), depth);
if (!success)
return; // aborted

Expand Down Expand Up @@ -366,18 +384,65 @@ namespace shellanything
}
}

void App::ClearLegacyLogsDirectory()
{
const std::string legacy_logs_dir = GetLegacyLogsDirectory();

// Search for log files directly under legacy_logs_dir
ra::strings::StringVector files;
static const int depth = 0; // Do not search recursively
bool success = ra::filesystem::FindFilesUtf8(files, legacy_logs_dir.c_str(), depth);
if (!success)
return; // aborted

// for each file found
for (size_t i = 0; i < files.size(); i++)
{
const std::string& file_path = files[i];

// Is that a configuration file ?
if (LoggerHelper::IsValidLogFile(file_path))
{
// It does not belongs there.
// Delete the file
SA_LOG(INFO) << "Deleting old legacy log file '" << file_path << "'.";
bool deleted = ra::filesystem::DeleteFileUtf8(file_path.c_str());
if (!deleted)
{
SA_LOG(ERROR) << "Failed deleting old legacy log file '" << file_path << "'.";
}
}
}

// Check if the directory is empty.
// We need to make this check before calling ra::filesystel::DeleteDirectory() because the
// DeleteDirectory function will automatically delete remaining files in order to delete the directory.
// We need to make sure the directory is empty first.
bool empty = ra::filesystem::IsDirectoryEmptyUtf8(legacy_logs_dir);
if (empty)
{
// Now it is safe to delete the directory
SA_LOG(INFO) << "Deleting old legacy log directory '" << legacy_logs_dir << "'.";
ra::filesystem::DeleteDirectoryUtf8(legacy_logs_dir.c_str());
}
else
{
SA_LOG(ERROR) << "Skipped deleting old legacy log directory '" << legacy_logs_dir << "'. The directory is not empty. The directory likely contains files that are not log files.";
}
}

void App::InitConfigManager()
{
shellanything::ConfigManager& cmgr = shellanything::ConfigManager::GetInstance();

std::string legacy_dir = GetLegacyConfigurationsDirectory();
std::string config_dir = GetConfigurationsDirectory();

bool first_run = IsFirstApplicationRun(app_name, app_version);
if (first_run)
{
SA_LOG(INFO) << "First application launch.";
ClearLegacyConfigurationDirectory(legacy_dir); // Issue #108 moved Configuration Files directory to a new location.
ClearLegacyConfigurationDirectory(); // Issue #108 moved Configuration Files directory to a new location.
ClearLegacyLogsDirectory(); // Issue #108 delete previous logs directory.
InstallDefaultConfigurations(config_dir);
}

Expand All @@ -394,10 +459,10 @@ namespace shellanything
//get home directory of the user
std::string home_dir = ra::user::GetHomeDirectoryUtf8();
std::string config_dir = GetConfigurationsDirectory();
std::string log_dir = ra::unicode::AnsiToUtf8(GetLogDirectory());
std::string log_dir = GetLogDirectory();

SA_LOG(INFO) << "HOME directory : " << home_dir.c_str();
SA_LOG(INFO) << "Config directory : " << config_dir.c_str();
SA_LOG(INFO) << "CONFIG directory : " << config_dir.c_str();
SA_LOG(INFO) << "LOG directory : " << log_dir.c_str();

//define global properties
Expand Down
17 changes: 15 additions & 2 deletions src/core/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ namespace shellanything
/// <returns>Returns true if application is loaded in a test environment. Returns false otherwise.</returns>
bool IsTestingEnvironment();

/// <summary>
/// Get the application's legacy log directory. The returned directory has write access.
/// </summary>
/// <returns>Returns the path of the legacy directory that was used by the logging framework.</returns>
std::string GetLegacyLogsDirectory();

/// <summary>
/// Get the application's log directory. The returned directory has write access.
/// </summary>
Expand Down Expand Up @@ -242,9 +248,16 @@ namespace shellanything
void InstallDefaultConfigurations(const std::string& dest_dir);

/// <summary>
/// Moved any Configuration Files from the given legacy directory to the official configurations directory.
/// Moved any Configuration Files from the legacy directory to the official configurations directory.
/// The term legacy refers to version 0.9.0 and older.
/// </summary>
void ClearLegacyConfigurationDirectory();

/// <summary>
/// Delete any log files from the legacy logs directory.
/// The term legacy refers to version 0.9.0 and older.
/// </summary>
void ClearLegacyConfigurationDirectory(const std::string& legacy_dir);
void ClearLegacyLogsDirectory();

/// <summary>
/// Initialize the Configuration Manager to the user's stall the original configuration files to the specified destination directory.
Expand Down
23 changes: 23 additions & 0 deletions src/core/LoggerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <string>

#include "rapidassist/strings.h"
#include "rapidassist/filesystem_utf8.h"
#include "rapidassist/unicode.h"

namespace shellanything
{
Expand Down Expand Up @@ -127,6 +129,27 @@ namespace shellanything
return has_vebose_logging;
}

bool LoggerHelper::IsValidLogFile(const std::string& path)
{
std::string file_extension = ra::filesystem::GetFileExtention(path);
file_extension = ra::strings::Uppercase(file_extension);

if (file_extension != "LOG")
return false;

// Peek at the file for validating content
std::string data;
bool peeked = ra::filesystem::PeekFileUtf8(path, 1024 * 1024, data);
if (!peeked)
return false;

bool valid = ra::unicode::IsValidUtf8(data.c_str());
if (!valid)
return false; // the file might contain binary data

return true;
}

// ------------------------------------------------------------------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------------------------------------------------------------------

Expand Down
7 changes: 7 additions & 0 deletions src/core/LoggerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ namespace shellanything
/// <returns>Returns true when verbose logging is enabled. Returns false otherwise.</returns>
static bool IsVerboseLoggingEnabled();

/// <summary>
/// Detect if a given file is a valid log file.
/// </summary>
/// <param name="path">The file path to check</param>
/// <returns>Returns true if the file is a valid log file. Returns false otherwise.</returns>
static bool IsValidLogFile(const std::string& path);

private:
ILoggerService::LOG_LEVEL mLevel;
bool mIsVerboseStream;
Expand Down

0 comments on commit 0513e63

Please sign in to comment.