GCLM_Deploy.exe not working - tries to show dialog in non-interactive session

Posted by: mike on 3 May 2021, 11:20 pm EST

  • Posted 3 May 2021, 11:20 pm EST

    After just having upgraded from AR13 to AR15, I'm trying to make use of the new pipeline licensing feature in our CI environment (as outlined here: https://www.grapecity.com/activereportsnet/docs/v15/online/licensing-with-pipelines.html)

    The latest GCLM_Deploy.exe is downloaded and executed, however it freezes my build process because it tries to throw up a dialog (LicenseManagerDeploy.MainWindow) despite it not running in an interactive session. If Environment.UserInteractive is false, you should not be throwing up dialogs and instead output any messages to the console, or log file, and also use an ExitCode to represent success or failure.

    When I run the dialog during an interactive session, it throws up a dialog (see attached image for screenshot). I assume it is trying to do the same during a non-interactive session.

    Below is a stack trace my CI software gave after terminating the process.


    [IL Method without Metadata]

    at System.Windows.MessageBox.ShowCore(System.IntPtr owner, System.String messageBoxText, System.String caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon, System.Windows.MessageBoxResult defaultResult, System.Windows.MessageBoxOptions options)

    at System.Windows.MessageBox.Show(System.Windows.Window owner, System.String messageBoxText, System.String caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon)

    at GrapeCity.LicenseManagerDeploy.MainWindow.<MainWindow_Loaded>b__1_0(System.Object s, System.EventArgs args)

    at System.Windows.Threading.DispatcherTimer.FireTick(System.Object unused)

    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, System.Object args, System.Int32 numArgs)

    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object source, System.Delegate callback, System.Object args, System.Int32 numArgs, System.Delegate catchHandler)

    at System.Windows.Threading.DispatcherOperation.InvokeImpl()

    at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object state)

    at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx)

    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx)

    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state)

    at MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state)

    at System.Windows.Threading.DispatcherOperation.Invoke()

    at System.Windows.Threading.Dispatcher.ProcessQueue()

    at System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, System.Int32 msg, System.IntPtr wParam, System.IntPtr lParam, System.Boolean& handled)

    at MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, System.Int32 msg, System.IntPtr wParam, System.IntPtr lParam, System.Boolean& handled)

    at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object o)

    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, System.Object args, System.Int32 numArgs)

    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object source, System.Delegate callback, System.Object args, System.Int32 numArgs, System.Delegate catchHandler)

    at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, System.Object args, System.Int32 numArgs)

    at MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, System.Int32 msg, System.IntPtr wParam, System.IntPtr lParam)

    M-->U

    [IL Method without Metadata]

    at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)

    at System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame)

    at System.Windows.Application.RunDispatcher(System.Object ignore)

    at System.Windows.Application.RunInternal(System.Windows.Window window)

    at System.Windows.Application.Run(System.Windows.Window window)

    at GrapeCity.LicenseManagerDeploy.App.Main()
  • Replied 6 May 2021, 5:13 am EST

    Hello,

    Can you please check with attached gclm.

    Thanks,
    Mohit
    gclm.zip
  • Replied 6 May 2021, 6:19 am EST

    The existing/current gclm.exe works fine for me. This version you sent to me is about 7 months older than the most recent (May 2020 vs January 2021), and when it is runs it just prompts me to update to the latest.

    My problem lies in your deployment tool GCLM_Deploy.exe. It is the tool that deploys an embedded glcm.exe (always the latest if the files on the URI are well-maintained). The tool is meant for use in automated build pipelines (as explained in your help documentation).

    When used in a normal Windows session (with a GUI), it throws up an unnecessary dialog while it successfully unpacks its GLCM.exe to the "%ProgramData%\GrapeCity\GCLM" folder.

    However, when used in a UI-less build pipeline on a minimally provisioned virtual machine (the purpose the tool was designed for) it fails because it tries to throw up that dialog. It fails to throw up the dialog because there is no GUI in which to show the dialog.

    Thus, the tool doesn't seem to work for the purpose for which it was designed.

    Ideally, such a tool should check whether it's in an interactive environment (Environment.UserInteractive in .NET Framework), and show the dialog if True, use console.writeline if False.

    I could certainly copy the gclm.exe tool to each new instance of the build pipeline machine from my own local copy, but that sort of defeats the purpose of the deployment tool. Doing it that way, I'd need to keep it up to date manually (if some breaking change be introduced). Which again, seems to break the promise of the intended design.

    Anyway, I'll cobble together a workaround. I just wanted to let you know that it could use some improvement if it is to be relied upon in various build pipeline solutions.
  • Replied 6 May 2021, 6:16 pm EST

    Hello,

    I have escalated the issue to the development team(AR-26530) and will inform you once I get any information from them.

    Thanks,
    Mohit
  • Replied 10 May 2021, 5:04 am EST

    Hello,

    Can you please share the detail information of your "UI-less build pipeline" environment.

    Thanks,
    Mohit
  • Replied 10 May 2021, 5:18 am EST

    I myself an using JetBrains TeamCity, but lots of Continuous Integration solutions use "build agents" that run as a Windows Service, and you cannot render to a GUI via a Windows Service. Similarly, some Continuous Integration solutions can use a docker container to achieve the same effect. The end goal is that fresh build agents can be spun up and discarded as needed. The number of available build agents can be increased to meet demand if needed (though I myself am running a fixed-number of build agents). Your system allows for me to run the build that needs ActiveReports on any of my build agents rather than on just a single agent. This means I'm less likely to have to wait in a build queue for a specific build agent that has the a fixed AR license.

    As I said, I was able to work around it -- but it would be nice if your deployment tool (GCLM_DEPLOY.EXE) did the "proper" thing and didn't attempt to show a window to a user that isn't there to see it.

    Environment.UserInteractive, available in all flavors of .NET, can be used to suppress any dialogs. When in this mode, any warnings or error information should be shunted to the console (Console.WriteLine). And if an error occurs, set a non-zero ExitCode (since Continuous Integration build agents can halt a build when this happens).

    https://docs.microsoft.com/en-us/dotnet/api/system.environment.userinteractive?view=net-5.0

    Thanks,
    -Mike
  • Replied 10 May 2021, 5:25 am EST

    I should have added that the reason for sending any error messages to the console is so that those messages will be logged in the build output for the continuous integration solution. I would be able to see in my build logs an error like: "Unable to contact Grape City License Server, please check your internet connection or try again later". That particular sample message is more relevant to GCLM.EXE than GCLM_Deploy.EXE, but I'm sure you can see what I'm trying to convey.

    If GLCM.EXE were to throw up an error message with an "Ok" dialog when there's an error, it would likely freeze my build agent and it would sit there doing nothing (waiting for input it will never get) until that specific action or the build as a whole reaches it's designed timeout. For GLCM.EXE, I'd probably set that to 1 minute, where my build as a whole is set to time out at 25 minutes.
  • Replied 10 May 2021, 7:21 am EST

    Oh, I guess I should warn you of another potential problem running GCLM_Deploy.exe as a non-Administrator (which is best practices when running build agents)...

    %ProgramData%, be default, is writable by normal users, but normal users cannot modify or delete files. So, when first dropping off GLCM.exe, be sure to modify the rights to the files you drop off to allow for future overwrites by GLCM_Deploy.exe.

    It might already do this. But just in case, you should pass that along to anyone who might be looking into things.
  • Replied 11 May 2021, 3:02 pm EST

    Hello,

    Thanks for you feedback. I have share the same with the development team.

    Thanks,
    Mohit
Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels