1

I am attempting to schedule a CefSharp rendering of pages stored in SharePoint via a SharePoint Timer Job. However, the OWSTIMER.exe service crashes almost immediately after calling Cef.Initialize(), throwing next to no errors.

The Subscription Class is:

internal class Subscriptions: IDisposable
{
    internal Subscriptions()
    {
        db = // CreateConnection();

        if (Cef.IsInitialized == false)
        {
            var settings = new CefSettings
            {
                CachePath = "cache",
                BrowserSubprocessPath = "ProjectBin\\CefSharp.BrowserSubprocess.exe",
                LogSeverity = LogSeverity.Default,
            };

            Cef.Initialize(settings);
        }
    }

    internal void RunTodaysSubscriptions()
    {
        var subs = db.tt_ScheduledJobs.Where(sj => sj.Date <= DateTime.Today).Select(sj => sj.tt_Subscription).ToList();

        foreach (var sub in subs)
        {
            ExecuteSubscription(sub);
            SetNextSchedule(sub);
        }
    }

    private void ExecuteSubscription(tt_Subscription subscription)
    {
        tt_JobHistory historyEntry = new tt_JobHistory();

        historyEntry.SubscriptionKey = subscription.SubscriptionKey;
        historyEntry.StartDate = DateTime.Now;
        historyEntry.Status = "In Progress";

        dfe.tt_JobHistory.Add(historyEntry);
        dfe.SaveChanges();

        string url = //path to file

        using (SubscriptionExecution se = new SubscriptionExecution(
               url,
               subscription.SubscriptionKey,
               subscription.Format))
        {
            //Completed represents either a response from the dashboard that the export either succeded
            //or failed. If there is no response (i.e. a javascript error preventing the dashboard from executing
            //an export, then we would hit the timeout of 5 minutes and shutdown this process.
            if (SpinWait.SpinUntil(() => se.Completed == true, 120000) == true)
            {
                //Had a response from dashboard, could be a success or failure
                if (se.ServerModel.Success == true) SuccessHistoryEntry(historyEntry);
                else ErrorHistoryEntry(se.ServerModel.Message, historyEntry);
            }
            else
            {
                ErrorHistoryEntry("Process timed out generating subscription", historyEntry);

            }
        }

        db.SaveChanges();
    }
    // ...
}

SubscriptionExecution is:

internal class SubscriptionExecution : IDisposable
{
    // ...

    internal SubscriptionExecution(string url, int subscriptionId, string fileType, string logLocation)
    {
        LogLocation = logLocation;

        SubscriptionId = subscriptionId;
        FileType = fileType;
        Completed = false;

        ServerModel = new ServerModel();
        ServerModel.PropertyChanged += new PropertyChangedEventHandler(ServerModel_PropertyChanged);

        browser = new ChromiumWebBrowser(url);

        browser.RegisterJsObject("serverModel", ServerModel);
        browser.LoadingStateChanged += LoadingStateChanged;
        if (LogLocation != string.Empty) browser.ConsoleMessage += BrowserConsoleMessage;
    }

    private void ServerModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Success")
        {
            Completed = true;
        }
    }

    // ...
}

There's a loadingStateChange function that injects some javascript that modifies the ServerModel.Success field when an event happens.

However, I can't seem to get this far. Except in one specific circumstance, the timerjob reaches the Cef.Initialize(settings) section, and then immediately restarts. Unfortunately, outside the event log, there is no error message to be found.

In the Windows Event Log, there is Windows Event Viewer: Error in OWSTIMER.exe which is indicating an error in libcef.dll

I've installed the libcef.dll.pdb symbols for this version of cefsharp (v57). The CefSharp troubleshooting guide suggests that in instances like this, there should be logfiles or error dumps. There should be a file 'debug.log' in the folder with the executable, and perhaps a mini crashdump file in AppData\Local\CrashDumps.

However, as this is a SharePoint Timer job, these files don't seem to be appearing. I did find a debug.log file inside the 15 hive bin (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN); however this file is empty.

I can't find the CrashDumps folder anywhere; checked under all user accounts on the machine, especially the running account and the SharePoint Timer Job managed account.

The one specific circumstance that I can get the code to run without restarting the timer job is immediately after the server is restarted. Restarting the server has (temporarily) fixed a few other problems around this issue, and so I suspect it might be related. Namely, I have had trouble retracting and redeploying the farm solution. This throws a couple of different errors:

  • on retracting: <SERVER>: The process cannot access the file 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN...\icudtl.dat' because it is being used by another process.
    Error: The removal of this file failed: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN...\icudtl.dat.
  • on deploying: The requested operation cannot be performed on a file with a user-mapped section open.

I've attempted to find what other process is using icudtl.dat using Process Explorer, but all I could find was chrome, which was accessing a different copy. Killing all chrome processes and trying again also did not solve the problem.

BM-
  • 616
  • 5
  • 15
  • Read the release notes on Github, CEF now uses crashpad for error reporting, you can configure crashdumps. – amaitland Apr 28 '17 at 08:17

0 Answers0