NetSparkleUpdater / NetSparkle

NetSparkle is a C#, cross-platform, highly-configurable software update framework with pre-built UI for .NET developers compatible with .NET 4.6.2/.NET 6+, WinForms, WPF, and Avalonia; uses Ed25519 signatures. View basic usage here in the README and try the samples for yourself.
https://netsparkleupdater.github.io/NetSparkle/
MIT License
606 stars 84 forks source link

Question: Location of update config #460

Closed christophwille closed 1 year ago

christophwille commented 1 year ago

In my trials I saw this ouput:

netsparkle: Starting update loop...
netsparkle: Reading config...
netsparkle: Update check performed within the last 1440 minutes!

Where is that information written to? (and would it be configurable?)

Deadpikle commented 1 year ago

Good question. Depends on your OS. If Windows, see the RegistryConfiguration class. If other OS, see the JSONConfiguration class.

Nothing stopping you from using the JSONConfiguration class on all OS's, you'd just need to set/configure it as needed via the Configuration property on SparkleUpdater:

https://github.com/NetSparkleUpdater/NetSparkle/blob/12f10ddc33738485e208f64964a9cb448007c393/src/NetSparkle/SparkleUpdater.cs#L241-L267

The path/location is configurable in either case. For JSONConfiguration, see the following: https://github.com/NetSparkleUpdater/NetSparkle/blob/12f10ddc33738485e208f64964a9cb448007c393/src/NetSparkle/Configurations/JSONConfiguration.cs#L96-L127

For RegistryConfiguration, see the following: https://github.com/NetSparkleUpdater/NetSparkle/blob/12f10ddc33738485e208f64964a9cb448007c393/src/NetSparkle/Configurations/RegistryConfiguration.cs#L93-L124

So, basically, for the JSONConfiguration, you can simply pass in your own object with a different path in its constructor. Or for more complex use cases subclass JSONConfiguration and override the GetSavePath() method.

christophwille commented 1 year ago

I tried with

_sparkle = new SparkleUpdater(
                "https://ilspy.net/appcast.xml",
                new Ed25519Checker(SecurityMode.Strict, "")
            ) {
                UIFactory = new NetSparkleUpdater.UI.WPF.UIFactory(null),
                RelaunchAfterUpdate = false,
                CustomInstallerArguments = "",
                Configuration = new JSONConfiguration(null, sparkleSettingsPath)
            };

This will crash with

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=NetSparkle
  StackTrace:
   at NetSparkleUpdater.Configurations.JSONConfiguration.GetSavePath()
   at NetSparkleUpdater.Configurations.JSONConfiguration..ctor(IAssemblyAccessor assemblyAccessor, String savePath)
   at ICSharpCode.ILSpy.MainWindow.MainWindow_Loaded(Object sender, RoutedEventArgs e) in D:\GitWorkspace\ILSpy\ILSpy\MainWindow.xaml.cs:line 912
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.BroadcastEventHelper.BroadcastEvent(DependencyObject root, RoutedEvent routedEvent)
   at System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(Object root)
   at System.Windows.Media.MediaContext.FireLoadedPendingCallbacks()
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.Resize(ICompositionTarget resizedCompositionTarget)
   at System.Windows.Interop.HwndTarget.OnResize()
   at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

Did some digging and finally found it - ctor of JsonConfiguration:

_savePath = savePath != null && string.IsNullOrWhiteSpace(savePath) ? savePath : GetSavePath();

There is one small thing missing - the "not" (!) before string.IsNullOrWhiteSpace(savePath)