private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(txtName.Text))
                {
                    throw new Exception("Il nome è un campo obbligatorio!");
                }

                var dictionaryParameters = new Dictionary <string, string>();

                //se in inserimento verifica che il nome sia univoco
                if (btnSave.Text.ToLower() == "inserisci")
                {
                    var duplicate = _jl.appoggio.FirstOrDefault(x => x.name == txtName.Text);
                    if (duplicate != null)
                    {
                        throw new Exception($"Il nome del lavoro {txtName.Text} esiste già!");
                    }

                    //verifica che sia stato selezionato uno zip
                    if (string.IsNullOrEmpty(txtPath.Text))
                    {
                        throw new Exception("Occorre selezionare un file .Zip !");
                    }

                    //verifica che nello zip ci sia una cartella plugin
                    //verifica che ci sia un solo file fuori dalla cartella plugin
                    var trovatoEntryPoint = 0;
                    using (var zip = ZipFile.Read(txtPath.Text))
                    {
                        foreach (var z in zip)
                        {
                            if (z.FileName.ToUpper().Contains("JOB"))
                            {
                                if (!Path.GetExtension(z.FileName).Contains("dll"))
                                {
                                    continue;
                                }
                                trovatoEntryPoint++;
                                txtEntryPoint.Text = z.FileName;
                            }
                        }
                    }

                    if (trovatoEntryPoint != 1)
                    {
                        throw new Exception("Nel file .Zip NON ESISTE un'unica .DLL denominata 'Job.dll'!");
                    }

                    //estrai tutto
                    _jl.ExtractZipJob(txtPath.Text, txtName.Text);
                    //ricava il nome della classe dall'entrypoint
                    var pathAssembly = $"CustomJobs/{txtName.Text}/{txtEntryPoint.Text}";
                    var assembly     =
                        Assembly.LoadFrom(pathAssembly);
                    var types = assembly.GetTypes();
                    var job   = new Job
                    {
                        name       = txtName.Text,
                        path       = pathAssembly,
                        entrypoint = txtEntryPoint.Text,
                        parameters = dictionaryParameters
                    };
                    foreach (var t in types)
                    {
                        var interfaces = t.GetInterfaces();
                        if (interfaces.All(i => i != typeof(IJob)))
                        {
                            continue;
                        }
                        job.scheduleclass = t.FullName;
                        var properties = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                        foreach (var prop in properties)
                        {
                            dictionaryParameters.Add(prop.Name, "");
                        }
                    }

                    _jl.appoggio.Add(job);
                }
                else
                {
                    dictionaryParameters =
                        dt.AsEnumerable().ToDictionary(row => row[0].ToString(), row => row[1].ToString());

                    var inmodifica = _jl.appoggio.FirstOrDefault(x => x.name == txtName.Text);
                    if (inmodifica != null)
                    {
                        inmodifica.parameters = dictionaryParameters;
                    }
                }

                _jl.SaveJobConfig();

                Close();
            }
            catch (Exception ex)
            {
                if (ex is ReflectionTypeLoadException)
                {
                    var typeLoadException = ex as ReflectionTypeLoadException;
                    var loaderExceptions  = typeLoadException.LoaderExceptions;

                    MessageBox.Show(loaderExceptions[0].Message);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }