rodneyviana / ODSyncService

OneDrive service/DLL for Sync State
MIT License
93 stars 26 forks source link

Support for local user profile containing non english letters #24

Open bjorgehoksnes opened 3 years ago

bjorgehoksnes commented 3 years ago

Hello, we are using ODSyncService to monitor the OneDrive status of our clients. However we are facing an issue caused by Windows Autopilot on some of our clients.

Using WIndows Autopilot in an cloud only enviroment the local user profile folder uses the display name of the user rather than the UPN. For some of our clients that means that the user profile contains norwegian letters, ie. æ, ø, å. ODSyncService is not able to run when this is the case, and that also means that OneDrive.exe itself is unable to run.

This is an excellent piece of software so it would be awesome if this could be fixed.

rodneyviana commented 3 years ago

Hi Bjorge (let me know if it is not your name),

The funny thing is that I meant to make it compatible with any language by using Unicode, but what you don't test you may be surprised. Can you please ask the user to open command prompt in regular mode (not elevated) and show me the result of:

echo [%LOCALAPPDATA%\\OneDriveMonitor]

Thanks,

Rodney

bjorgehoksnes commented 3 years ago

I've replaced the actual user name with a different one that contains a norwegian letter and so would have the same issue:

echo [%LOCALAPPDATA%\\OneDriveMonitor] [C:\Users\BårdTufteJohansen\AppData\Local\\OneDriveMonitor]

frankemann commented 3 years ago

+1 for norwegian letter support :)

rodneyviana commented 3 years ago

Hi Norwegian Users,

I created a user using the name you provided and I could not reproduce the problem, so I ask your help to troubleshoot when the problem happens. Please run this test application CppConsoleApplication.exe logged as one of the users showing the problem.

Run this way:

CppConsoleApplication.exe >out.txt
notepad out.txt

And let me know the content of the file. Also see if the folder was created and if the log file is there.

This is the source code of the app if you want to compile yourself:

#include <Windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <fstream>
#include <locale>
#include <codecvt>
#include <string>
#pragma comment(lib, "DbgHelp")

using namespace std;

wstring logFolder;

enum sev
{
    Verbose,
    Information,
    Warning,
    Error
};

wstring GetLogFolder()
{
    if (logFolder.size() > 0)
        return logFolder;
    logFolder = wstring(MAX_PATH, '\0');
    DWORD count = MAX_PATH;

    count = ::ExpandEnvironmentStrings(L"%LOCALAPPDATA%\\OneDriveMonitor", const_cast<wchar_t*>(logFolder.c_str()), count);
    logFolder.resize(count - 1);
    wprintf(L"Folder: %s\n", logFolder.c_str());
    BOOL created = ::CreateDirectory(logFolder.c_str(), NULL);
    HRESULT hr = ::GetLastError();
    if (FALSE == created && hr != ERROR_ALREADY_EXISTS)
    {
        wprintf(L"HR=%x - Unable to create folder %s\n", hr, logFolder.c_str());
        exit(hr);
        //PrintErrorAndExit(hr, L"Unable to create folder " + logFolder);
    }

    logFolder.append(L"\\Logs");
    wprintf(L"Folder: %s\n", logFolder.c_str());
    created = ::CreateDirectory(logFolder.c_str(), NULL);
    hr = ::GetLastError();
    if (FALSE == created && hr != ERROR_ALREADY_EXISTS)
    {
        wprintf(L"HR=%x - Unable to create folder %s\n", hr, logFolder.c_str());
        exit(hr);
        //PrintErrorAndExit(hr, L"Unable to create folder " + logFolder);
    }
    logFolder.append(L"\\");
    wprintf(L"Folder: %s\n", logFolder.c_str());
    return logFolder;

}

wstring format(const wchar_t* formatStr, ...)
{
    va_list args;
    va_start(args, formatStr);
    auto len = _vscwprintf(formatStr, args);
    va_end(args);
    std::wstring result((size_t)len, L'\0');

    va_start(args, formatStr);
    auto count = _vsnwprintf_s(const_cast<wchar_t*>(result.c_str()), len + 1, len + 1, formatStr, args);
    va_end(args);
    return result;
}

wstring GetTimeAnsi()
{
    SYSTEMTIME st;
    ::GetLocalTime(&st);
    auto timeStr = format(L"%04d-%02d-%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    return timeStr;
}
wstring GetFileName()
{
    SYSTEMTIME st;
    ::GetLocalTime(&st);
    auto timeStr = format(L"OneDriveMonitor_%04d-%02d-%02d.log", st.wYear, st.wMonth, st.wDay);
    return GetLogFolder() + timeStr;

}

void Log(wstring Message, wstring source = L"TestApp", sev severity = sev::Information)
{
    const int s_AttachId = 1234;
    wstring sevStr;
    switch (severity)
    {
    case sev::Error:
        sevStr = L"Error      ";
        break;
    case sev::Information:
        sevStr = L"Information";
        break;
    case sev::Verbose:
        sevStr = L"Verbose    ";
        break;
    case sev::Warning:
        sevStr = L"Warning    ";
        break;
    }

    //if (s_AttachId == 0)
    //{
    //  auto hr = g_System->GetCurrentProcessSystemId(&s_AttachId);
    //  wprintf(L"PID=%d,hr=%d\n", s_AttachId, hr);

    //}

    wstring logLine = format(L"%s\t%s\t%s\t%s\t%d",
        GetTimeAnsi().c_str(),
        sevStr.c_str(),
        source.c_str(),
        Message.c_str(),
        s_AttachId
    );
    wofstream file;
    file.open(GetFileName(), ios_base::app | ios::out);
    file << logLine << endl;
    file.close();
}

int main()
{
    Log(L"Hello");
}
bjorgehoksnes commented 3 years ago

Thanks for the quick response! I've run the app and it seems to work just fine. The folders are created and the log file written to. OneDriveMonitor_2021-04-29.log out.txt

rodneyviana commented 3 years ago

Hi BJorge,

I put together a new version of the PowerShell cmdlet that is compatible with On Demand status. You won't need the monitoring app for this, but you can test in a machine being monitored if you want. So use it as the regular PowerShell library:

Import-Module .\OneDriveLib.dll # add path if necessary
Get-ODStatus

Download here: PowerShell On Demand Beta

This version is not signed, so check the ZIP hash after you download and unblock. To check the hash of the ZIP in PowerShell, run:

Get-FileHash -Algorithm SHA256 -Path ".\OneDriveLib_OnDemand.zip" # add path if necessary

The SHA256 Hash of the ZIP file (not the DLL) is:

9CB1AE6BEB201400ADD168CA8E4E6DAADD0FD9023D62774E6998F449962CC158

PLEASE let me know if it works

frankemann commented 3 years ago

Hi. I just tested this and it seems to work, somehow. StatusTring shows up "Updated" on every Sharepoint site I have synced with On-Demand. On my own Business OneDrive the StatusString shows: "Fulladet (100%)"

"Fulladet" in norwegian translates to "Fully Charged 100%". (Almost so I think it's reading the batterystatus......? image

rodneyviana commented 3 years ago

Hi Frankemann,

Thank you for testing. There was indeed an error that always returned the first icon as ordered by Windows API and since my OneDrive is in the first icon I did not see the bug. The new patch is here: New ODStatus with fixed icon

This version is not signed, so check the ZIP hash after you download and unblock. To check the hash of the ZIP in PowerShell, run:

Get-FileHash -Algorithm SHA256 -Path ".\OneDriveLib_OnDemand_1.zip" # add path if necessary

The SHA256 Hash of the ZIP file (not the DLL) is:

571A5DAFC4783AC3CD85A7985A33CD40E633BE805884C9F5316494BF3E7779DC

The SHA256 Hash of the DLL is:

Get-FileHash -Algorithm SHA256 -Path ".\OneDriveLib.dll" # Add path if necessary

7E5BA351B6C39DC9C541F77E46134520E2084F6CB41B6C36641DD4211E956140

PLEASE let me know if it works You may keep using this version if it works

rodneyviana commented 3 years ago

Hi Frankemann,

I made some improvement and published the code. I am waiting for your test and my new signing certificate since the current one expired. You can download this release candidate here: OneDriveLib.dll

You will need to unblock the file before using it.

The SHA256 hash is:

361874F5478E52A9FFACB61234F98C982905C7CC00259BB95A3C2A164C2E5DC7
frankemann commented 3 years ago

Hi. We are now getting the correct StatusString for the Onedrive.

But the StatusString for other synced Sharepoint sites has now changed from correct status to: StatusString : Status not found for type [Sitename)

We were looking for a monitorsolution for the Onedrive so in that way we are very happy. Hopefully the status from other synced sites will be a bonus eventually.

When we run the get-odstatus we also see the taskbar is blinking and all the icons on the desktop is refreshing. Since we will run this as a script regulary I am concerned if this will affect the users visually.

bjorgehoksnes commented 3 years ago

Can confirm that the StatusString for OneDrive is correct now, but other synced sites return an error code: StatusString : <ERROR>Status not found for type [Site name]

Being able to monitor OneDrive status this way is great. However I agree with frankemann that the "blinking" while get-odstatus is running might alarm the users somewhat. :)

Thanks for the quick updates so far, awesome work!

rodneyviana commented 3 years ago

Hi. We are now getting the correct StatusString for the Onedrive.

But the StatusString for other synced Sharepoint sites has now changed from correct status to: StatusString : Status not found for type [Sitename)

We were looking for a monitorsolution for the Onedrive so in that way we are very happy. Hopefully the status from other synced sites will be a bonus eventually.

When we run the get-odstatus we also see the taskbar is blinking and all the icons on the desktop is refreshing. Since we will run this as a script regulary I am concerned if this will affect the users visually.

Frankemann,

Are you by any chance running the monitoring in a loop or using -path? What is the command you issue to see the blinking?

Thanks,

Rodney

frankemann commented 3 years ago

Hi. I am just starting up Powershell (in user mode) and typing the following:

Import-Module .\OneDriveLib.dll Get-ODStatus

rodneyviana commented 3 years ago

Final signed version with support for On Demand is available

frankemann commented 3 years ago

Hi. Onedrive status is good, but synceed sharepoint libraries shows (erro nostatus text found). That's not an issue for us since since we are primarily looking for monitoring Onedrive itself. But would be nice if we also could check the synced library for error at the customers computers.

The -OnDemandOnly resolves the flicker issues. Tha's very nice, thanks!

frankemann commented 3 years ago

Important:

On Demand Status ONLY works if OneDrive icon is visible on the taskbar

Do you know a powershellscript we can use to enable that the icons is visible on the tasbkbar?