Browse Source

fixed cancel button bug. implemented simple trigger display. begin implementation of server connection MRU.

quartznet-1.0
jvilalta 15 years ago
parent
commit
527f0e9b0a
11 changed files with 1677 additions and 1181 deletions
  1. +203
    -192
      ClickForensics.Quartz.Manager/ClickForensics.Quartz.Manager.csproj
  2. +14
    -0
      ClickForensics.Quartz.Manager/ConnectionInfo.cs
  3. +416
    -380
      ClickForensics.Quartz.Manager/MainForm.cs
  4. +311
    -311
      ClickForensics.Quartz.Manager/QuartzScheduler.cs
  5. +37
    -0
      ClickForensics.Quartz.Manager/RegistryStore.cs
  6. +144
    -142
      ClickForensics.Quartz.Manager/ServerConnectForm.Designer.cs
  7. +43
    -37
      ClickForensics.Quartz.Manager/ServerConnectForm.cs
  8. +119
    -119
      ClickForensics.Quartz.Manager/ServerConnectForm.resx
  9. +215
    -0
      ClickForensics.Quartz.Manager/SimpleTriggerDisplay.Designer.cs
  10. +55
    -0
      ClickForensics.Quartz.Manager/SimpleTriggerDisplay.cs
  11. +120
    -0
      ClickForensics.Quartz.Manager/SimpleTriggerDisplay.resx

+ 203
- 192
ClickForensics.Quartz.Manager/ClickForensics.Quartz.Manager.csproj View File

@@ -1,199 +1,210 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D23DACFA-11A1-480E-A6C4-1F37B564523D}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ClickForensics.Quartz.Manager</RootNamespace>
<AssemblyName>ClickForensics.Quartz.Manager</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Common.Logging">
<HintPath>..\lib\Common.Logging.dll</HintPath>
</Reference>
<Reference Include="Quartz">
<HintPath>..\lib\Quartz.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AddJobForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddJobForm.Designer.cs">
<DependentUpon>AddJobForm.cs</DependentUpon>
</Compile>
<Compile Include="AddListenerForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddListenerForm.Designer.cs">
<DependentUpon>AddListenerForm.cs</DependentUpon>
</Compile>
<Compile Include="ErrorDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ErrorDialog.Designer.cs">
<DependentUpon>ErrorDialog.cs</DependentUpon>
</Compile>
<Compile Include="JobType.cs" />
<Compile Include="NativeJobDetailDisplay.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="NativeJobDetailDisplay.Designer.cs">
<DependentUpon>NativeJobDetailDisplay.cs</DependentUpon>
</Compile>
<Compile Include="JobNode.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="AddJobForm.resx">
<DependentUpon>AddJobForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="AddListenerForm.resx">
<DependentUpon>AddListenerForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="CronTriggerDisplay.resx">
<DependentUpon>CronTriggerDisplay.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ErrorDialog.resx">
<DependentUpon>ErrorDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="NativeJobDetailDisplay.resx">
<DependentUpon>NativeJobDetailDisplay.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="ServerConnectForm.resx">
<DependentUpon>ServerConnectForm.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="QuartzScheduler.cs" />
<Compile Include="SchedulerNode.cs" />
<Compile Include="ServerConnectForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ServerConnectForm.Designer.cs">
<DependentUpon>ServerConnectForm.cs</DependentUpon>
</Compile>
<Compile Include="CronTriggerDisplay.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="CronTriggerDisplay.Designer.cs">
<DependentUpon>CronTriggerDisplay.cs</DependentUpon>
</Compile>
<Compile Include="TriggerNode.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="JobAssemblies.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D23DACFA-11A1-480E-A6C4-1F37B564523D}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ClickForensics.Quartz.Manager</RootNamespace>
<AssemblyName>ClickForensics.Quartz.Manager</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Common.Logging">
<HintPath>..\lib\Common.Logging.dll</HintPath>
</Reference>
<Reference Include="Quartz">
<HintPath>..\lib\Quartz.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AddJobForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddJobForm.Designer.cs">
<DependentUpon>AddJobForm.cs</DependentUpon>
</Compile>
<Compile Include="AddListenerForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddListenerForm.Designer.cs">
<DependentUpon>AddListenerForm.cs</DependentUpon>
</Compile>
<Compile Include="ConnectionInfo.cs" />
<Compile Include="SimpleTriggerDisplay.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="SimpleTriggerDisplay.Designer.cs">
<DependentUpon>SimpleTriggerDisplay.cs</DependentUpon>
</Compile>
<Compile Include="ErrorDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ErrorDialog.Designer.cs">
<DependentUpon>ErrorDialog.cs</DependentUpon>
</Compile>
<Compile Include="JobType.cs" />
<Compile Include="NativeJobDetailDisplay.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="NativeJobDetailDisplay.Designer.cs">
<DependentUpon>NativeJobDetailDisplay.cs</DependentUpon>
</Compile>
<Compile Include="JobNode.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="AddJobForm.resx">
<DependentUpon>AddJobForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="AddListenerForm.resx">
<DependentUpon>AddListenerForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SimpleTriggerDisplay.resx">
<DependentUpon>SimpleTriggerDisplay.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="CronTriggerDisplay.resx">
<DependentUpon>CronTriggerDisplay.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ErrorDialog.resx">
<DependentUpon>ErrorDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="NativeJobDetailDisplay.resx">
<DependentUpon>NativeJobDetailDisplay.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="ServerConnectForm.resx">
<DependentUpon>ServerConnectForm.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="QuartzScheduler.cs" />
<Compile Include="RegistryMRU.cs" />
<Compile Include="SchedulerNode.cs" />
<Compile Include="ServerConnectForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ServerConnectForm.Designer.cs">
<DependentUpon>ServerConnectForm.cs</DependentUpon>
</Compile>
<Compile Include="CronTriggerDisplay.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="CronTriggerDisplay.Designer.cs">
<DependentUpon>CronTriggerDisplay.cs</DependentUpon>
</Compile>
<Compile Include="TriggerNode.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="JobAssemblies.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
-->
</Project>

+ 14
- 0
ClickForensics.Quartz.Manager/ConnectionInfo.cs View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClickForensics.Quartz.Manager
{
public class ConnectionInfo
{
public string ServerName { get; set; }
public int Port { get; set; }
public string SchedulerName { get; set; }
}
}

+ 416
- 380
ClickForensics.Quartz.Manager/MainForm.cs View File

@@ -1,380 +1,416 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Quartz;
using Quartz.Collection;
using System.Net.Sockets;
//using ClickForensics.Quartz.Jobs;
using System.IO;

namespace ClickForensics.Quartz.Manager
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
jobGroupsTreeView.AfterSelect += new TreeViewEventHandler(jobGroupsTreeView_AfterSelect);
ctxScheduler.Opening += new CancelEventHandler(ctxScheduler_Opening);
jobGroupsTreeView.MouseDown += new MouseEventHandler(jobGroupsTreeView_MouseDown);

}

void ctxScheduler_Opening(object sender, CancelEventArgs e)
{

}

void jobGroupsTreeView_AfterSelect(object sender, TreeViewEventArgs e)
{
jobDetailsToggle(false);
if (e.Node is TriggerNode || e.Node is JobNode)
{
btnDeleteJob.Enabled = true;
}
else
{
btnDeleteJob.Enabled = false;
}

if (e.Node is JobNode)
{
btnRunJobNow.Enabled = true;
pnlDetails.Controls.Add(new NativeJobDetailDisplay(((JobNode)e.Node).Detail));
jobDetailsToggle(true);
}
else
{
btnRunJobNow.Enabled = false;

}
if (e.Node is TriggerNode)
{
btnPause.Enabled = true;
setPauseButtonText();
if (((TriggerNode)e.Node).Trigger is CronTrigger)
{
pnlDetails.Controls.Add(new CronTriggerDisplay((CronTrigger)((TriggerNode)e.Node).Trigger));
jobDetailsToggle(true);
}
btnEdit.Enabled = true;
}
else
{
btnEdit.Enabled = false;
btnPause.Enabled = false;
}
}

private void setPauseButtonText()
{
TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
string name = node.Trigger.Name;
string group = node.Trigger.Group;
if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused)
{
btnPause.Text = "Resume";
}
else
{
btnPause.Text = "Pause";
}
}

private void connectToolStripMenuItem_Click(object sender, EventArgs e)
{
using (ServerConnectForm form = new ServerConnectForm())
{
form.ShowDialog();
try
{
Scheduler = new QuartzScheduler(form.Server, form.Port, form.Scheduler);
serverConnectStatusLabel.Text = string.Format("Connected to {0}", Scheduler.Address);
connectToolStripMenuItem.Enabled = false;
jobsToolStripMenuItem.Enabled = true;
loadJobGroups();
updateRunningJobs();
}
catch (SocketException ex)
{
ErrorDialog dialog = new ErrorDialog();
dialog.Message = string.Format("Unable to connect to scheduler {0} on {1}:{2}", form.Scheduler, form.Server, form.Port);
dialog.Description = ex.Message;
dialog.ShowDialog();
}
form.Close();
}
//loadGlobalTriggers();
}

//private void loadGlobalTriggers()
//{
// foreach (IJobListener jobListener in Scheduler.GetScheduler().GetJobDetail(null,null)..GlobalJobListeners)
// {
// globalTriggersListView.Items.Add(jobListener.Name);
// }
//}

private void loadJobGroups()
{

try
{
this.Cursor = Cursors.WaitCursor;

jobDetailsToggle(false);
jobGroupsTreeView.Nodes.Clear();
SchedulerNode schedulerNode = new SchedulerNode(Scheduler);
schedulerNode.ContextMenuStrip = ctxScheduler;
jobGroupsTreeView.Nodes.Add(schedulerNode);
TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Job Groups");
string[] jobGroups = Scheduler.GetScheduler().JobGroupNames;
foreach (string jobGroup in jobGroups)
{
TreeNode jobGroupNode = jobGroupsNode.Nodes.Add(jobGroup);
TreeNode jobsNode = jobGroupNode.Nodes.Add("Jobs");
addJobNodes(jobsNode);
}

jobGroupsTreeView.Nodes[0].Expand();
jobGroupsNode.Expand();

StripStatusLabel_Job_Groups.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss");

}
finally
{
this.Cursor = Cursors.Default;
}


}

private void jobDetailsToggle(bool isVisible)
{
if (isVisible == false)
{
pnlDetails.Controls.Clear();
}
}

void jobGroupsTreeView_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
TreeNode node = jobGroupsTreeView.GetNodeAt(e.X, e.Y);
if (node != null)
{
jobGroupsTreeView.SelectedNode = node;
ctxScheduler.Show(jobGroupsTreeView, e.Location);
}
}
}
//private void loadJobs()
//{
// foreach (TreeNode node in jobGroupsTreeView.Nodes)
// {
// addJobNodes(node);
// }
//}

private void addJobNodes(TreeNode node)
{
string group = node.Parent.Text;
string[] jobs = Scheduler.GetScheduler().GetJobNames(group);
foreach (string jobName in jobs)
{
try
{
JobDetail detail = Scheduler.GetScheduler().GetJobDetail(jobName, group);
JobNode jobNode = new JobNode(detail);
node.Nodes.Add(jobNode);
addTriggerNodes(jobNode);
addListenerNodes(jobNode);
}
catch (Exception ex)
{
//TODO: Do something useful with this exception. Most likely cause is the client does not have a copy of a given dll and can't load the type.
}
}
}

private void addListenerNodes(JobNode node)
{
string jobName = node.Text;
string jobGroupName = node.Parent.Text;
string[] listenerNames = node.Detail.JobListenerNames;
foreach (string listener in listenerNames)
{
node.Text = string.Format("JL {0}", listenerNames);
}
//ISet set = Scheduler.GetScheduler().JobListenerNames;
}

private void addTriggerNodes(TreeNode treeNode)
{
Trigger[] triggers = Scheduler.GetScheduler().GetTriggersOfJob(treeNode.Text, treeNode.Parent.Parent.Text);
TreeNode triggersNode = treeNode.Nodes.Add("Triggers");
foreach (Trigger trigger in triggers)
{
TriggerNode node = new TriggerNode(trigger);
triggersNode.Nodes.Add(node);
}

}
private void updateRunningJobs()
{
try
{
this.Cursor = Cursors.WaitCursor;

timer_Refresh_Running_Jobs.Stop();

listView_RunningJobs.Items.Clear();

DataTable table = Scheduler.GetRunningJobs();
foreach (DataRow row in table.Rows)
{
//JobName JobDuration
ListViewItem item = new ListViewItem(new string[] { Convert.ToString(row["JobName"]), Convert.ToString(row["Runtime"]) });
listView_RunningJobs.Items.Add(item);
}
StripStatusLabel_Jobs_Refresh_date.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss");


//reset the timer ( documentation not clear if .stop = restart @ 0 in timing, but changing the interval sure should do that. )
int timer_was = timer_Refresh_Running_Jobs.Interval;
timer_Refresh_Running_Jobs.Interval = timer_was + 1;
timer_Refresh_Running_Jobs.Interval = timer_was;

timer_Refresh_Running_Jobs.Start();
}
finally
{
this.Cursor = Cursors.Default;
}
}
public QuartzScheduler Scheduler { get; set; }

private void addGlobalListenerToolStripMenuItem_Click(object sender, EventArgs e)
{
AddListenerForm form = new AddListenerForm();
form.ListenerInterface = typeof(IJobListener);
form.ShowDialog();
JobDataMap map = new JobDataMap();
map.Add("type", form.ListenerType);
//Scheduler.ScheduleOneTimeJob(typeof(AddJobListenerJob), map, 0);
loadJobGroups();
}

private void addJobListenerToolStripMenuItem_Click(object sender, EventArgs e)
{
TreeNode selectedNode = jobGroupsTreeView.SelectedNode;
if (selectedNode != null && selectedNode is JobNode)
{
AddListenerForm form = new AddListenerForm();
form.ListenerInterface = typeof(IJobListener);
form.ShowDialog();
//JobHistoryListener listener = new JobHistoryListener();
//listener.Name = null;
//((JobNode)selectedNode).Detail.AddJobListener();
}
}

private void addJobToolStripMenuItem_Click(object sender, EventArgs e)
{
AddJobForm form = new AddJobForm();
form.ShowDialog();
if (form.JobDetail != null && form.Trigger != null)
{
Scheduler.GetScheduler().ScheduleJob(form.JobDetail, form.Trigger);
loadJobGroups();
}
}

private void btnRefreshRunningJobs_Click(object sender, EventArgs e)
{
updateRunningJobs();
}

private void btnRefreshJobGroups_Click(object sender, EventArgs e)
{
loadJobGroups();
}

private void btnRunJobNow_Click(object sender, EventArgs e)
{
JobNode node = (JobNode)jobGroupsTreeView.SelectedNode;
string job = node.Detail.Name;
string group = node.Detail.Group;
Scheduler.GetScheduler().TriggerJobWithVolatileTrigger(job, group);
}

private void btnDeleteJob_Click(object sender, EventArgs e)
{
TreeNode selectedNode = jobGroupsTreeView.SelectedNode;
if (selectedNode is JobNode)
{
JobNode node = (JobNode)jobGroupsTreeView.SelectedNode;
string job = node.Detail.Name;
string group = node.Detail.Group;
Scheduler.GetScheduler().DeleteJob(job, group);
jobGroupsTreeView.SelectedNode.Remove();

}
if (selectedNode is TriggerNode)
{
Scheduler.GetScheduler().UnscheduleJob(((TriggerNode)selectedNode).Trigger.Name, ((TriggerNode)selectedNode).Trigger.Group);
}

//loadJobGroups();
}

private void btnPause_Click(object sender, EventArgs e)
{
TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
string name = node.Trigger.Name;
string group = node.Trigger.Group;
if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused)
{
Scheduler.GetScheduler().ResumeTrigger(name, group);
}
else
{
Scheduler.GetScheduler().PauseTrigger(name, group);
}
setPauseButtonText();
}

private void btnEdit_Click(object sender, EventArgs e)
{
TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
AddJobForm form = new AddJobForm(node);
form.ShowDialog();
if (form.JobDetail != null && form.Trigger != null)
{
Scheduler.GetScheduler().RescheduleJob(node.Trigger.Name, node.Trigger.Group, form.Trigger);
loadJobGroups();
}
}

private void backupToolStripMenuItem_Click(object sender, EventArgs e)
{
QuartzScheduler scheduler = ((SchedulerNode)((TreeView)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl).SelectedNode).Scheduler;
FileDialog dialog = new SaveFileDialog();
dialog.ShowDialog();
FileInfo file = new FileInfo(dialog.FileName);
scheduler.BackupToFile(file);
}

private void timer_Refresh_Running_Jobs_Tick(object sender, EventArgs e)
{
updateRunningJobs();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Quartz;
using Quartz.Collection;
using System.Net.Sockets;
//using ClickForensics.Quartz.Jobs;
using System.IO;
namespace ClickForensics.Quartz.Manager
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
jobGroupsTreeView.AfterSelect += new TreeViewEventHandler(jobGroupsTreeView_AfterSelect);
ctxScheduler.Opening += new CancelEventHandler(ctxScheduler_Opening);
jobGroupsTreeView.MouseDown += new MouseEventHandler(jobGroupsTreeView_MouseDown);
}
void ctxScheduler_Opening(object sender, CancelEventArgs e)
{
}
void jobGroupsTreeView_AfterSelect(object sender, TreeViewEventArgs e)
{
jobDetailsToggle(false);
if (e.Node is TriggerNode || e.Node is JobNode)
{
btnDeleteJob.Enabled = true;
}
else
{
btnDeleteJob.Enabled = false;
}
if (e.Node is JobNode)
{
btnRunJobNow.Enabled = true;
pnlDetails.Controls.Add(new NativeJobDetailDisplay(((JobNode)e.Node).Detail));
jobDetailsToggle(true);
}
else
{
btnRunJobNow.Enabled = false;
}
if (e.Node is TriggerNode)
{
btnPause.Enabled = true;
setPauseButtonText();
if (((TriggerNode)e.Node).Trigger is CronTrigger)
{
pnlDetails.Controls.Add(new CronTriggerDisplay((CronTrigger)((TriggerNode)e.Node).Trigger));
jobDetailsToggle(true);
}
if (((TriggerNode)e.Node).Trigger is SimpleTrigger)
{
pnlDetails.Controls.Add(new SimpleTriggerDisplay((SimpleTrigger)((TriggerNode)e.Node).Trigger));
jobDetailsToggle(true);
}
btnEdit.Enabled = true;
}
else
{
btnEdit.Enabled = false;
btnPause.Enabled = false;
}
}
private void setPauseButtonText()
{
TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
string name = node.Trigger.Name;
string group = node.Trigger.Group;
if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused)
{
btnPause.Text = "Resume";
}
else
{
btnPause.Text = "Pause";
}
}
private void connectToolStripMenuItem_Click(object sender, EventArgs e)
{
using (ServerConnectForm form = new ServerConnectForm())
{
form.ShowDialog();
if (form.Cancelled)
{
return;
}
try
{
Scheduler = new QuartzScheduler(form.Server, form.Port, form.Scheduler);
serverConnectStatusLabel.Text = string.Format("Connected to {0}", Scheduler.Address);
connectToolStripMenuItem.Enabled = false;
jobsToolStripMenuItem.Enabled = true;
loadJobGroups();
updateRunningJobs();
}
catch (SocketException ex)
{
ErrorDialog dialog = new ErrorDialog();
dialog.Message = string.Format("Unable to connect to scheduler {0} on {1}:{2}", form.Scheduler, form.Server, form.Port);
dialog.Description = ex.Message;
dialog.ShowDialog();
}
form.Close();
}
//loadGlobalTriggers();
}
//private void loadGlobalTriggers()
//{
// foreach (IJobListener jobListener in Scheduler.GetScheduler().GetJobDetail(null,null)..GlobalJobListeners)
// {
// globalTriggersListView.Items.Add(jobListener.Name);
// }
//}
private void loadJobGroups()
{
try
{
this.Cursor = Cursors.WaitCursor;
jobDetailsToggle(false);
jobGroupsTreeView.Nodes.Clear();
SchedulerNode schedulerNode = new SchedulerNode(Scheduler);
schedulerNode.ContextMenuStrip = ctxScheduler;
jobGroupsTreeView.Nodes.Add(schedulerNode);
TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Job Groups");
string[] jobGroups = Scheduler.GetScheduler().JobGroupNames;
foreach (string jobGroup in jobGroups)
{
TreeNode jobGroupNode = jobGroupsNode.Nodes.Add(jobGroup);
TreeNode jobsNode = jobGroupNode.Nodes.Add("Jobs");
addJobNodes(jobsNode);
}
jobGroupsTreeView.Nodes[0].Expand();
jobGroupsNode.Expand();
StripStatusLabel_Job_Groups.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss");
loadOrphanJobs(schedulerNode);
loadStuckTriggers(schedulerNode);
}
finally
{
this.Cursor = Cursors.Default;
}
}
private void loadStuckTriggers(SchedulerNode schedulerNode)
{
TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Stuck Triggers");
}
private void loadOrphanJobs(SchedulerNode schedulerNode)
{
TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Orphan Jobs");
}
private void jobDetailsToggle(bool isVisible)
{
if (isVisible == false)
{
pnlDetails.Controls.Clear();
}
}
void jobGroupsTreeView_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
TreeNode node = jobGroupsTreeView.GetNodeAt(e.X, e.Y);
if (node != null)
{
jobGroupsTreeView.SelectedNode = node;
ctxScheduler.Show(jobGroupsTreeView, e.Location);
}
}
}
//private void loadJobs()
//{
// foreach (TreeNode node in jobGroupsTreeView.Nodes)
// {
// addJobNodes(node);
// }
//}
private void addJobNodes(TreeNode node)
{
string group = node.Parent.Text;
string[] jobs = Scheduler.GetScheduler().GetJobNames(group);
foreach (string jobName in jobs)
{
try
{
JobDetail detail = Scheduler.GetScheduler().GetJobDetail(jobName, group);
JobNode jobNode = new JobNode(detail);
node.Nodes.Add(jobNode);
addTriggerNodes(jobNode);
addListenerNodes(jobNode);
}
catch (Exception ex)
{
node.Nodes.Add(string.Format("Unknown Job Type ({0})", jobName));
//TODO: Do something useful with this exception. Most likely cause is the client does not have a copy of a given dll and can't load the type.
}
}
}
private void addListenerNodes(JobNode node)
{
string jobName = node.Text;
string jobGroupName = node.Parent.Text;
string[] listenerNames = node.Detail.JobListenerNames;
foreach (string listener in listenerNames)
{
node.Text = string.Format("JL {0}", listenerNames);
}
//ISet set = Scheduler.GetScheduler().JobListenerNames;
}
private void addTriggerNodes(TreeNode treeNode)
{
Trigger[] triggers = Scheduler.GetScheduler().GetTriggersOfJob(treeNode.Text, treeNode.Parent.Parent.Text);
TreeNode triggersNode = treeNode.Nodes.Add("Triggers");
foreach (Trigger trigger in triggers)
{
TriggerNode node = new TriggerNode(trigger);
triggersNode.Nodes.Add(node);
addCalendarNode(node);
}
}
private void addCalendarNode(TriggerNode node)
{
if (node.Trigger.CalendarName != null)
{
//TODO: Convert this to a CalendarNode and implement CalendarDisplay controls
node.Nodes.Add(node.Trigger.CalendarName);
}
else
{
node.Nodes.Add("No calendar found");
}
}
private void updateRunningJobs()
{
try
{
this.Cursor = Cursors.WaitCursor;
timer_Refresh_Running_Jobs.Stop();
listView_RunningJobs.Items.Clear();
DataTable table = Scheduler.GetRunningJobs();
foreach (DataRow row in table.Rows)
{
//JobName JobDuration
ListViewItem item = new ListViewItem(new string[] { Convert.ToString(row["JobName"]), Convert.ToString(row["Runtime"]) });
listView_RunningJobs.Items.Add(item);
}
StripStatusLabel_Jobs_Refresh_date.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss");
//reset the timer ( documentation not clear if .stop = restart @ 0 in timing, but changing the interval sure should do that. )
int timer_was = timer_Refresh_Running_Jobs.Interval;
timer_Refresh_Running_Jobs.Interval = timer_was + 1;
timer_Refresh_Running_Jobs.Interval = timer_was;
timer_Refresh_Running_Jobs.Start();
}
finally
{
this.Cursor = Cursors.Default;
}
}
public QuartzScheduler Scheduler { get; set; }
private void addGlobalListenerToolStripMenuItem_Click(object sender, EventArgs e)
{
AddListenerForm form = new AddListenerForm();
form.ListenerInterface = typeof(IJobListener);
form.ShowDialog();
JobDataMap map = new JobDataMap();
map.Add("type", form.ListenerType);
//Scheduler.ScheduleOneTimeJob(typeof(AddJobListenerJob), map, 0);
loadJobGroups();
}
private void addJobListenerToolStripMenuItem_Click(object sender, EventArgs e)
{
TreeNode selectedNode = jobGroupsTreeView.SelectedNode;
if (selectedNode != null && selectedNode is JobNode)
{
AddListenerForm form = new AddListenerForm();
form.ListenerInterface = typeof(IJobListener);
form.ShowDialog();
//JobHistoryListener listener = new JobHistoryListener();
//listener.Name = null;
//((JobNode)selectedNode).Detail.AddJobListener();
}
}
private void addJobToolStripMenuItem_Click(object sender, EventArgs e)
{
AddJobForm form = new AddJobForm();
form.ShowDialog();
if (form.JobDetail != null && form.Trigger != null)
{
Scheduler.GetScheduler().ScheduleJob(form.JobDetail, form.Trigger);
loadJobGroups();
}
}
private void btnRefreshRunningJobs_Click(object sender, EventArgs e)
{
updateRunningJobs();
}
private void btnRefreshJobGroups_Click(object sender, EventArgs e)
{
loadJobGroups();
}
private void btnRunJobNow_Click(object sender, EventArgs e)
{
JobNode node = (JobNode)jobGroupsTreeView.SelectedNode;
string job = node.Detail.Name;
string group = node.Detail.Group;
Scheduler.GetScheduler().TriggerJobWithVolatileTrigger(job, group);
}
private void btnDeleteJob_Click(object sender, EventArgs e)
{
TreeNode selectedNode = jobGroupsTreeView.SelectedNode;
if (selectedNode is JobNode)
{
JobNode node = (JobNode)jobGroupsTreeView.SelectedNode;
string job = node.Detail.Name;
string group = node.Detail.Group;
Scheduler.GetScheduler().DeleteJob(job, group);
jobGroupsTreeView.SelectedNode.Remove();
}
if (selectedNode is TriggerNode)
{
Scheduler.GetScheduler().UnscheduleJob(((TriggerNode)selectedNode).Trigger.Name, ((TriggerNode)selectedNode).Trigger.Group);
}
//loadJobGroups();
}
private void btnPause_Click(object sender, EventArgs e)
{
TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
string name = node.Trigger.Name;
string group = node.Trigger.Group;
if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused)
{
Scheduler.GetScheduler().ResumeTrigger(name, group);
}
else
{
Scheduler.GetScheduler().PauseTrigger(name, group);
}
setPauseButtonText();
}
private void btnEdit_Click(object sender, EventArgs e)
{
TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
AddJobForm form = new AddJobForm(node);
form.ShowDialog();
if (form.JobDetail != null && form.Trigger != null)
{
Scheduler.GetScheduler().RescheduleJob(node.Trigger.Name, node.Trigger.Group, form.Trigger);
loadJobGroups();
}
}
private void backupToolStripMenuItem_Click(object sender, EventArgs e)
{
QuartzScheduler scheduler = ((SchedulerNode)((TreeView)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl).SelectedNode).Scheduler;
FileDialog dialog = new SaveFileDialog();
dialog.ShowDialog();
FileInfo file = new FileInfo(dialog.FileName);
scheduler.BackupToFile(file);
}
private void timer_Refresh_Running_Jobs_Tick(object sender, EventArgs e)
{
updateRunningJobs();
}
}
}

+ 311
- 311
ClickForensics.Quartz.Manager/QuartzScheduler.cs View File

@@ -1,311 +1,311 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections.Specialized;
using Quartz.Impl;
using Quartz;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
namespace ClickForensics.Quartz.Manager
{
public class QuartzScheduler
{
public QuartzScheduler(string server, int port, string scheduler)
{
Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler);
_schedulerFactory = new StdSchedulerFactory(getProperties(Address));
try
{
_scheduler = _schedulerFactory.GetScheduler();
}
catch (SchedulerException se)
{
MessageBox.Show("Unable to connect to the specified server", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
public string Address { get; private set; }
private NameValueCollection getProperties(string address)
{
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "RemoteClient";
properties["quartz.scheduler.proxy"] = "true";
properties["quartz.threadPool.threadCount"] = "0";
properties["quartz.scheduler.proxy.address"] = address;
return properties;
}
public IScheduler GetScheduler()
{
return _scheduler;
}
public DataTable GetJobs()
{
DataTable table = new DataTable();
table.Columns.Add("GroupName");
table.Columns.Add("JobName");
table.Columns.Add("JobDescription");
table.Columns.Add("TriggerName");
table.Columns.Add("TriggerGroupName");
table.Columns.Add("TriggerType");
table.Columns.Add("TriggerState");
table.Columns.Add("NextFireTime");
table.Columns.Add("PreviousFireTime");
string[] jobGroups = GetScheduler().JobGroupNames;
foreach (string group in jobGroups)
{
string[] jobNames = GetScheduler().GetJobNames(group);
foreach (string job in jobNames)
{
JobDetail detail = GetScheduler().GetJobDetail(job, group);
Trigger[] triggers = GetScheduler().GetTriggersOfJob(job, group);
foreach (Trigger trigger in triggers)
{
DataRow row = table.NewRow();
row["GroupName"] = group;
row["JobName"] = job;
row["JobDescription"] = detail.Description;
row["TriggerName"] = trigger.Name;
row["TriggerGroupName"] = trigger.Group;
row["TriggerType"] = trigger.GetType().Name;
row["TriggerState"] = GetScheduler().GetTriggerState(trigger.Name, trigger.Group);
DateTime? nextFireTime = trigger.GetNextFireTimeUtc();
if (nextFireTime != null)
{
row["NextFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime((DateTime)nextFireTime);
}
DateTime? previousFireTime = trigger.GetPreviousFireTimeUtc();
if (previousFireTime != null)
{
row["PreviousFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime((DateTime)previousFireTime);
}
table.Rows.Add(row);
}
}
}
return table;
}
public void ScheduleOneTimeJob(Type jobType, JobDataMap dataMap, int clientID)
{
string name = string.Format("{0}-{1}", jobType.Name, clientID);
string group = clientID.ToString();
JobDetail jobDetail = new JobDetail(name, group, jobType);
jobDetail.Description = "One time job";
jobDetail.Durable = false;
jobDetail.Group = group;
jobDetail.JobDataMap = dataMap;
jobDetail.JobType = jobType;
jobDetail.Name = name;
jobDetail.Volatile = true;
SimpleTrigger trigger = new SimpleTrigger();
trigger.Name = name;
trigger.Group = group;
trigger.StartTimeUtc = DateTime.UtcNow;
trigger.RepeatCount = 0;
trigger.RepeatInterval = TimeSpan.Zero;
GetScheduler().ScheduleJob(jobDetail, trigger);
}
private ISchedulerFactory _schedulerFactory;
private IScheduler _scheduler;
public DataTable GetRunningJobs()
{
DataTable table = new DataTable();
table.Columns.Add("JobName", typeof(string));
table.Columns.Add("RunTime", typeof(int));
try
{
IList jobs = GetScheduler().GetCurrentlyExecutingJobs();
foreach (JobExecutionContext context in jobs)
{
DataRow row = table.NewRow();
row["JobName"] = context.JobDetail.Name;
row["RunTime"] = (DateTime.Now.ToUniversalTime() - (DateTime)context.FireTimeUtc).TotalMinutes;
table.Rows.Add(row);
}
}
catch (Exception ex)
{
//TODO: Let the user know we couldn't load the running jobs.
}
return table;
}
public void BackupToFile(System.IO.FileInfo file)
{
IScheduler scheduler = GetScheduler();
string[] jobGroupNames = scheduler.JobGroupNames;
List<JobDetail> jobDetails = new List<JobDetail>();
foreach (var jobGroup in jobGroupNames)
{
string[] jobNames = scheduler.GetJobNames(jobGroup);
foreach (var jobName in jobNames)
{
jobDetails.Add(scheduler.GetJobDetail(jobName, jobGroup));
}
}
writeToFile(file, jobDetails);
}
private void writeToFile(System.IO.FileInfo file, List<JobDetail> jobDetails)
{
using (StreamWriter writer = file.CreateText())
{
XNamespace ns = "http://quartznet.sourceforge.net/JobSchedulingData";
XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes")
, new XElement(ns + "quartz"
, new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance")
, new XAttribute("version", "1.0")
, new XAttribute("overwrite-existing-jobs", "true")
)
);
foreach (JobDetail detail in jobDetails)
{
doc.Root.Add(
new XElement(ns + "job"
, new XElement(ns + "job-detail"
, new XElement(ns + "name", detail.Name)
, new XElement(ns + "group", detail.Group)
, new XElement(ns + "description", detail.Description)
, new XElement(ns + "job-type", detail.JobType.FullName + "," + detail.JobType.Assembly.FullName)
, new XElement(ns + "volatile", detail.Volatile)
, new XElement(ns + "durable", detail.Durable)
, new XElement(ns + "recover", detail.RequestsRecovery)
, getJobDataMap(ns, detail.JobDataMap)
)
, getTriggers(ns, detail)
)
);
}
writer.Write(doc);
writer.Flush();
writer.Close();
}
}
private XElement getJobDataMap(XNamespace ns, JobDataMap jobDataMap)
{
XElement map = new XElement(ns + "job-data-map");
foreach (var key in jobDataMap.GetKeys())
{
map.Add(new XElement(ns + "entry"
, new XElement(ns + "key", key)
, new XElement(ns + "value", jobDataMap[key])
)
);
}
return map;
}
private XElement[] getTriggers(XNamespace ns, JobDetail detail)
{
Trigger[] triggers = _scheduler.GetTriggersOfJob(detail.Name, detail.Group);
XElement[] elements = new XElement[triggers.Length];
for (int i = 0; i < triggers.Length; i++)
{
elements[i] = new XElement(ns + "trigger");
if (triggers[i] is SimpleTrigger)
{
elements[i].Add(getSimpleTrigger(ns, (SimpleTrigger)triggers[i]));
}
else if (triggers[i] is CronTrigger)
{
elements[i].Add(getCronTrigger(ns, (CronTrigger)triggers[i]));
}
}
return elements;
}
private XElement getCronTrigger(XNamespace ns, CronTrigger trigger)
{
XElement cronTrigger = new XElement(ns + "cron");
addCommonTriggerData(ns, cronTrigger, trigger);
cronTrigger.Add(
new XElement(ns + "cron-expression", trigger.CronExpressionString)
);
return cronTrigger;
}
private void addCommonTriggerData(XNamespace ns, XElement rootTriggerElement, Trigger trigger)
{
rootTriggerElement.Add(
new XElement(ns + "name", trigger.Name)
, new XElement(ns + "group", trigger.Group)
, new XElement(ns + "description", trigger.Description)
, new XElement(ns + "misfire-instruction", getMisfireInstructionText(trigger))
, new XElement(ns + "volatile", trigger.Volatile)
, new XElement(ns + "job-name", trigger.JobName)
, new XElement(ns + "job-group", trigger.JobGroup)
);
}
private string getMisfireInstructionText(Trigger trigger)
{
if (trigger is CronTrigger)
{
return getCronTriggerMisfireInstructionText(trigger.MisfireInstruction);
}
return getSimpleTriggerMisfireInstructionText(trigger.MisfireInstruction);
}
private string getSimpleTriggerMisfireInstructionText(int misfireInstruction)
{
switch (misfireInstruction)
{
case 0:
return "SmartPolicy";
case 1:
return "FireNow";
case 2:
return "RescheduleNowWithExistingRepeatCount";
case 3:
return "RescheduleNowWithRemainingRepeatCount";
case 4:
return "RescheduleNextWithRemainingCount";
case 5:
return "RescheduleNextWithExistingCount";
default:
throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for SimpleTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction));
}
}
private string getCronTriggerMisfireInstructionText(int misfireInstruction)
{
switch (misfireInstruction)
{
case 0:
return "SmartPolicy";
case 1:
return "FireOnceNow";
case 2:
return "DoNothing";
default:
throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for CronTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction));
}
}
private XElement getSimpleTrigger(XNamespace ns, SimpleTrigger trigger)
{
XElement simpleTrigger = new XElement(ns + "simple");
addCommonTriggerData(ns, simpleTrigger, trigger);
simpleTrigger.Add(
new XElement(ns + "repeat-count", trigger.RepeatCount)
, new XElement(ns + "repeat-interval", trigger.RepeatInterval.Milliseconds)
);
return simpleTrigger;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections.Specialized;
using Quartz.Impl;
using Quartz;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
namespace ClickForensics.Quartz.Manager
{
public class QuartzScheduler
{
public QuartzScheduler(string server, int port, string scheduler)
{
Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler);
_schedulerFactory = new StdSchedulerFactory(getProperties(Address));
try
{
_scheduler = _schedulerFactory.GetScheduler();
}
catch (SchedulerException)
{
MessageBox.Show("Unable to connect to the specified server", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
public string Address { get; private set; }
private NameValueCollection getProperties(string address)
{
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "RemoteClient";
properties["quartz.scheduler.proxy"] = "true";
properties["quartz.threadPool.threadCount"] = "0";
properties["quartz.scheduler.proxy.address"] = address;
return properties;
}
public IScheduler GetScheduler()
{
return _scheduler;
}
public DataTable GetJobs()
{
DataTable table = new DataTable();
table.Columns.Add("GroupName");
table.Columns.Add("JobName");
table.Columns.Add("JobDescription");
table.Columns.Add("TriggerName");
table.Columns.Add("TriggerGroupName");
table.Columns.Add("TriggerType");
table.Columns.Add("TriggerState");
table.Columns.Add("NextFireTime");
table.Columns.Add("PreviousFireTime");
string[] jobGroups = GetScheduler().JobGroupNames;
foreach (string group in jobGroups)
{
string[] jobNames = GetScheduler().GetJobNames(group);
foreach (string job in jobNames)
{
JobDetail detail = GetScheduler().GetJobDetail(job, group);
Trigger[] triggers = GetScheduler().GetTriggersOfJob(job, group);
foreach (Trigger trigger in triggers)
{
DataRow row = table.NewRow();
row["GroupName"] = group;
row["JobName"] = job;
row["JobDescription"] = detail.Description;
row["TriggerName"] = trigger.Name;
row["TriggerGroupName"] = trigger.Group;
row["TriggerType"] = trigger.GetType().Name;
row["TriggerState"] = GetScheduler().GetTriggerState(trigger.Name, trigger.Group);
DateTime? nextFireTime = trigger.GetNextFireTimeUtc();
if (nextFireTime != null)
{
row["NextFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime((DateTime)nextFireTime);
}
DateTime? previousFireTime = trigger.GetPreviousFireTimeUtc();
if (previousFireTime != null)
{
row["PreviousFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime((DateTime)previousFireTime);
}
table.Rows.Add(row);
}
}
}
return table;
}
public void ScheduleOneTimeJob(Type jobType, JobDataMap dataMap, int clientID)
{
string name = string.Format("{0}-{1}", jobType.Name, clientID);
string group = clientID.ToString();
JobDetail jobDetail = new JobDetail(name, group, jobType);
jobDetail.Description = "One time job";
jobDetail.Durable = false;
jobDetail.Group = group;
jobDetail.JobDataMap = dataMap;
jobDetail.JobType = jobType;
jobDetail.Name = name;
jobDetail.Volatile = true;
SimpleTrigger trigger = new SimpleTrigger();
trigger.Name = name;
trigger.Group = group;
trigger.StartTimeUtc = DateTime.UtcNow;
trigger.RepeatCount = 0;
trigger.RepeatInterval = TimeSpan.Zero;
GetScheduler().ScheduleJob(jobDetail, trigger);
}
private ISchedulerFactory _schedulerFactory;
private IScheduler _scheduler;
public DataTable GetRunningJobs()
{
DataTable table = new DataTable();
table.Columns.Add("JobName", typeof(string));
table.Columns.Add("RunTime", typeof(int));
try
{
IList jobs = GetScheduler().GetCurrentlyExecutingJobs();
foreach (JobExecutionContext context in jobs)
{
DataRow row = table.NewRow();
row["JobName"] = context.JobDetail.Name;
row["RunTime"] = (DateTime.Now.ToUniversalTime() - (DateTime)context.FireTimeUtc).TotalMinutes;
table.Rows.Add(row);
}
}
catch (Exception ex)
{
//TODO: Let the user know we couldn't load the running jobs.
}
return table;
}
public void BackupToFile(System.IO.FileInfo file)
{
IScheduler scheduler = GetScheduler();
string[] jobGroupNames = scheduler.JobGroupNames;
List<JobDetail> jobDetails = new List<JobDetail>();
foreach (var jobGroup in jobGroupNames)
{
string[] jobNames = scheduler.GetJobNames(jobGroup);
foreach (var jobName in jobNames)
{
jobDetails.Add(scheduler.GetJobDetail(jobName, jobGroup));
}
}
writeToFile(file, jobDetails);
}
private void writeToFile(System.IO.FileInfo file, List<JobDetail> jobDetails)
{
using (StreamWriter writer = file.CreateText())
{
XNamespace ns = "http://quartznet.sourceforge.net/JobSchedulingData";
XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes")
, new XElement(ns + "quartz"
, new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance")
, new XAttribute("version", "1.0")
, new XAttribute("overwrite-existing-jobs", "true")
)
);
foreach (JobDetail detail in jobDetails)
{
doc.Root.Add(
new XElement(ns + "job"
, new XElement(ns + "job-detail"
, new XElement(ns + "name", detail.Name)
, new XElement(ns + "group", detail.Group)
, new XElement(ns + "description", detail.Description)
, new XElement(ns + "job-type", detail.JobType.FullName + "," + detail.JobType.Assembly.FullName)
, new XElement(ns + "volatile", detail.Volatile)
, new XElement(ns + "durable", detail.Durable)
, new XElement(ns + "recover", detail.RequestsRecovery)
, getJobDataMap(ns, detail.JobDataMap)
)
, getTriggers(ns, detail)
)
);
}
writer.Write(doc);
writer.Flush();
writer.Close();
}
}
private XElement getJobDataMap(XNamespace ns, JobDataMap jobDataMap)
{
XElement map = new XElement(ns + "job-data-map");
foreach (var key in jobDataMap.GetKeys())
{
map.Add(new XElement(ns + "entry"
, new XElement(ns + "key", key)
, new XElement(ns + "value", jobDataMap[key])
)
);
}
return map;
}
private XElement[] getTriggers(XNamespace ns, JobDetail detail)
{
Trigger[] triggers = _scheduler.GetTriggersOfJob(detail.Name, detail.Group);
XElement[] elements = new XElement[triggers.Length];
for (int i = 0; i < triggers.Length; i++)
{
elements[i] = new XElement(ns + "trigger");
if (triggers[i] is SimpleTrigger)
{
elements[i].Add(getSimpleTrigger(ns, (SimpleTrigger)triggers[i]));
}
else if (triggers[i] is CronTrigger)
{
elements[i].Add(getCronTrigger(ns, (CronTrigger)triggers[i]));
}
}
return elements;
}
private XElement getCronTrigger(XNamespace ns, CronTrigger trigger)
{
XElement cronTrigger = new XElement(ns + "cron");
addCommonTriggerData(ns, cronTrigger, trigger);
cronTrigger.Add(
new XElement(ns + "cron-expression", trigger.CronExpressionString)
);
return cronTrigger;
}
private void addCommonTriggerData(XNamespace ns, XElement rootTriggerElement, Trigger trigger)
{
rootTriggerElement.Add(
new XElement(ns + "name", trigger.Name)
, new XElement(ns + "group", trigger.Group)
, new XElement(ns + "description", trigger.Description)
, new XElement(ns + "misfire-instruction", getMisfireInstructionText(trigger))
, new XElement(ns + "volatile", trigger.Volatile)
, new XElement(ns + "job-name", trigger.JobName)
, new XElement(ns + "job-group", trigger.JobGroup)
);
}
private string getMisfireInstructionText(Trigger trigger)
{
if (trigger is CronTrigger)
{
return getCronTriggerMisfireInstructionText(trigger.MisfireInstruction);
}
return getSimpleTriggerMisfireInstructionText(trigger.MisfireInstruction);
}
private string getSimpleTriggerMisfireInstructionText(int misfireInstruction)
{
switch (misfireInstruction)
{
case 0:
return "SmartPolicy";
case 1:
return "FireNow";
case 2:
return "RescheduleNowWithExistingRepeatCount";
case 3:
return "RescheduleNowWithRemainingRepeatCount";
case 4:
return "RescheduleNextWithRemainingCount";
case 5:
return "RescheduleNextWithExistingCount";
default:
throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for SimpleTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction));
}
}
private string getCronTriggerMisfireInstructionText(int misfireInstruction)
{
switch (misfireInstruction)
{
case 0:
return "SmartPolicy";
case 1:
return "FireOnceNow";
case 2:
return "DoNothing";
default:
throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for CronTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction));
}
}
private XElement getSimpleTrigger(XNamespace ns, SimpleTrigger trigger)
{
XElement simpleTrigger = new XElement(ns + "simple");
addCommonTriggerData(ns, simpleTrigger, trigger);
simpleTrigger.Add(
new XElement(ns + "repeat-count", trigger.RepeatCount)
, new XElement(ns + "repeat-interval", trigger.RepeatInterval.Milliseconds)
);
return simpleTrigger;
}
}
}

+ 37
- 0
ClickForensics.Quartz.Manager/RegistryStore.cs View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
namespace ClickForensics.Quartz.Manager
{
public class RegistryStore
{
public static List<ConnectionInfo> GetLastConnections()
{
List<ConnectionInfo> lastConnections = new List<ConnectionInfo>();
RegistryKey key = Registry.CurrentUser.CreateSubKey("QuartzNetManager").CreateSubKey("MRUList");
if (key != null)
{
for (int i = 0; i < 5; i++)
{
ConnectionInfo info = (ConnectionInfo)key.GetValue(string.Format("connection{0}", i), null);
if (info != null)
{
lastConnections.Add(info);
}
}
}
key.Close();
return lastConnections;
}
public static void AddConnection(ConnectionInfo info)
{
}
private static object lockObject = new object();
}
}

+ 144
- 142
ClickForensics.Quartz.Manager/ServerConnectForm.Designer.cs View File

@@ -1,143 +1,145 @@
namespace ClickForensics.Quartz.Manager
{
partial class ServerConnectForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnConnect = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.txtServer = new System.Windows.Forms.TextBox();
this.txtPort = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtScheduler = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(32, 87);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(75, 23);
this.btnConnect.TabIndex = 3;
this.btnConnect.Text = "Connect";
this.btnConnect.UseVisualStyleBackColor = true;
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(115, 87);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 4;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(29, 12);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(41, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Server:";
//
// txtServer
//
this.txtServer.Location = new System.Drawing.Point(90, 9);
this.txtServer.Name = "txtServer";
this.txtServer.Size = new System.Drawing.Size(100, 20);
this.txtServer.TabIndex = 0;
//
// txtPort
//
this.txtPort.Location = new System.Drawing.Point(90, 35);
this.txtPort.Name = "txtPort";
this.txtPort.Size = new System.Drawing.Size(100, 20);
this.txtPort.TabIndex = 1;
this.txtPort.Text = "555";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(29, 38);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(29, 13);
this.label2.TabIndex = 8;
this.label2.Text = "Port:";
//
// txtScheduler
//
this.txtScheduler.Location = new System.Drawing.Point(90, 61);
this.txtScheduler.Name = "txtScheduler";
this.txtScheduler.Size = new System.Drawing.Size(100, 20);
this.txtScheduler.TabIndex = 2;
this.txtScheduler.Text = "QuartzScheduler";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(29, 64);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(55, 13);
this.label3.TabIndex = 10;
this.label3.Text = "Scheduler";
//
// ServerConnectForm
//
this.AcceptButton = this.btnConnect;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(227, 141);
this.Controls.Add(this.txtScheduler);
this.Controls.Add(this.label3);
this.Controls.Add(this.txtPort);
this.Controls.Add(this.label2);
this.Controls.Add(this.txtServer);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnConnect);
this.Name = "ServerConnectForm";
this.Text = "ServerConnectForm";
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtServer;
private System.Windows.Forms.TextBox txtPort;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtScheduler;
private System.Windows.Forms.Label label3;
}
namespace ClickForensics.Quartz.Manager
{
partial class ServerConnectForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnConnect = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.txtPort = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtScheduler = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.cboServer = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(32, 87);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(75, 23);
this.btnConnect.TabIndex = 3;
this.btnConnect.Text = "Connect";
this.btnConnect.UseVisualStyleBackColor = true;
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(115, 87);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 4;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(29, 12);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(41, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Server:";
//
// txtPort
//
this.txtPort.Location = new System.Drawing.Point(90, 35);
this.txtPort.Name = "txtPort";
this.txtPort.Size = new System.Drawing.Size(100, 20);
this.txtPort.TabIndex = 1;
this.txtPort.Text = "555";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(29, 38);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(29, 13);
this.label2.TabIndex = 8;
this.label2.Text = "Port:";
//
// txtScheduler
//
this.txtScheduler.Location = new System.Drawing.Point(90, 61);
this.txtScheduler.Name = "txtScheduler";
this.txtScheduler.Size = new System.Drawing.Size(100, 20);
this.txtScheduler.TabIndex = 2;
this.txtScheduler.Text = "QuartzScheduler";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(29, 64);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(55, 13);
this.label3.TabIndex = 10;
this.label3.Text = "Scheduler";
//
// cboServer
//
this.cboServer.FormattingEnabled = true;
this.cboServer.Location = new System.Drawing.Point(90, 8);
this.cboServer.Name = "cboServer";
this.cboServer.Size = new System.Drawing.Size(100, 21);
this.cboServer.TabIndex = 1;
this.cboServer.SelectedIndexChanged += new System.EventHandler(this.cboServer_SelectedIndexChanged);
//
// ServerConnectForm
//
this.AcceptButton = this.btnConnect;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(227, 141);
this.Controls.Add(this.cboServer);
this.Controls.Add(this.txtScheduler);
this.Controls.Add(this.label3);
this.Controls.Add(this.txtPort);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnConnect);
this.Name = "ServerConnectForm";
this.Text = "ServerConnectForm";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtPort;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtScheduler;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox cboServer;
}
}

+ 43
- 37
ClickForensics.Quartz.Manager/ServerConnectForm.cs View File

@@ -1,37 +1,43 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ClickForensics.Quartz.Manager
{
public partial class ServerConnectForm : Form
{
public ServerConnectForm()
{
InitializeComponent();
}

private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}

private void btnConnect_Click(object sender, EventArgs e)
{
Server = txtServer.Text;
Port = int.Parse(txtPort.Text);
Scheduler = txtScheduler.Text;
this.Close();
}
public string Server { get; set; }
public int Port { get; set; }
public string Scheduler { get; set; }

}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ClickForensics.Quartz.Manager
{
public partial class ServerConnectForm : Form
{
public ServerConnectForm()
{
InitializeComponent();
cboServer.DataSource = RegistryStore.GetLastConnections();
}
private void btnCancel_Click(object sender, EventArgs e)
{
Cancelled = true;
this.Close();
}
private void btnConnect_Click(object sender, EventArgs e)
{
Server = cboServer.Text;
Port = int.Parse(txtPort.Text);
Scheduler = txtScheduler.Text;
RegistryStore.AddConnection(new ConnectionInfo { ServerName = Server, Port = Port, SchedulerName = Scheduler });
this.Close();
}
public string Server { get; set; }
public int Port { get; set; }
public string Scheduler { get; set; }
public bool Cancelled { get; set; }
private void cboServer_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}

+ 119
- 119
ClickForensics.Quartz.Manager/ServerConnectForm.resx View File

@@ -1,120 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

+ 215
- 0
ClickForensics.Quartz.Manager/SimpleTriggerDisplay.Designer.cs View File

@@ -0,0 +1,215 @@
namespace ClickForensics.Quartz.Manager
{
partial class SimpleTriggerDisplay
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblName = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.lblGroup = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.lblDescription = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.lblPreviousFireTime = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.lblNextFireTime = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.lblRepeatCount = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.lblRepeatInterval = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// lblName
//
this.lblName.AutoSize = true;
this.lblName.Location = new System.Drawing.Point(116, 15);
this.lblName.Name = "lblName";
this.lblName.Size = new System.Drawing.Size(35, 13);
this.lblName.TabIndex = 3;
this.lblName.Text = "label2";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(14, 15);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(38, 13);
this.label3.TabIndex = 2;
this.label3.Text = "Name:";
//
// lblGroup
//
this.lblGroup.AutoSize = true;
this.lblGroup.Location = new System.Drawing.Point(116, 36);
this.lblGroup.Name = "lblGroup";
this.lblGroup.Size = new System.Drawing.Size(35, 13);
this.lblGroup.TabIndex = 5;
this.lblGroup.Text = "label4";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(14, 36);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(39, 13);
this.label5.TabIndex = 4;
this.label5.Text = "Group:";
//
// lblDescription
//
this.lblDescription.AutoSize = true;
this.lblDescription.Location = new System.Drawing.Point(116, 57);
this.lblDescription.Name = "lblDescription";
this.lblDescription.Size = new System.Drawing.Size(35, 13);
this.lblDescription.TabIndex = 7;
this.lblDescription.Text = "label6";
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(14, 57);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(63, 13);
this.label7.TabIndex = 6;
this.label7.Text = "Description:";
//
// lblPreviousFireTime
//
this.lblPreviousFireTime.AutoSize = true;
this.lblPreviousFireTime.Location = new System.Drawing.Point(116, 99);
this.lblPreviousFireTime.Name = "lblPreviousFireTime";
this.lblPreviousFireTime.Size = new System.Drawing.Size(35, 13);
this.lblPreviousFireTime.TabIndex = 9;
this.lblPreviousFireTime.Text = "label8";
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(14, 99);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(97, 13);
this.label9.TabIndex = 8;
this.label9.Text = "Previous Fire Time:";
//
// lblNextFireTime
//
this.lblNextFireTime.AutoSize = true;
this.lblNextFireTime.Location = new System.Drawing.Point(116, 78);
this.lblNextFireTime.Name = "lblNextFireTime";
this.lblNextFireTime.Size = new System.Drawing.Size(41, 13);
this.lblNextFireTime.TabIndex = 11;
this.lblNextFireTime.Text = "label10";
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(14, 78);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(78, 13);
this.label11.TabIndex = 10;
this.label11.Text = "Next Fire Time:";
//
// lblRepeatCount
//
this.lblRepeatCount.AutoSize = true;
this.lblRepeatCount.Location = new System.Drawing.Point(116, 121);
this.lblRepeatCount.Name = "lblRepeatCount";
this.lblRepeatCount.Size = new System.Drawing.Size(35, 13);
this.lblRepeatCount.TabIndex = 13;
this.lblRepeatCount.Text = "label8";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(14, 121);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(76, 13);
this.label2.TabIndex = 12;
this.label2.Text = "Repeat Count:";
//
// lblRepeatInterval
//
this.lblRepeatInterval.AutoSize = true;
this.lblRepeatInterval.Location = new System.Drawing.Point(116, 144);
this.lblRepeatInterval.Name = "lblRepeatInterval";
this.lblRepeatInterval.Size = new System.Drawing.Size(35, 13);
this.lblRepeatInterval.TabIndex = 15;
this.lblRepeatInterval.Text = "label8";
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(14, 144);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(83, 13);
this.label6.TabIndex = 14;
this.label6.Text = "Repeat Interval:";
//
// SimpleTriggerDisplay
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.lblRepeatInterval);
this.Controls.Add(this.label6);
this.Controls.Add(this.lblRepeatCount);
this.Controls.Add(this.label2);
this.Controls.Add(this.lblNextFireTime);
this.Controls.Add(this.label11);
this.Controls.Add(this.lblPreviousFireTime);
this.Controls.Add(this.label9);
this.Controls.Add(this.lblDescription);
this.Controls.Add(this.label7);
this.Controls.Add(this.lblGroup);
this.Controls.Add(this.label5);
this.Controls.Add(this.lblName);
this.Controls.Add(this.label3);
this.Name = "SimpleTriggerDisplay";
this.Size = new System.Drawing.Size(324, 168);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblName;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label lblGroup;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label lblDescription;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label lblPreviousFireTime;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label lblNextFireTime;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Label lblRepeatCount;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label lblRepeatInterval;
private System.Windows.Forms.Label label6;
}
}

+ 55
- 0
ClickForensics.Quartz.Manager/SimpleTriggerDisplay.cs View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Quartz;
namespace ClickForensics.Quartz.Manager
{
public partial class SimpleTriggerDisplay : UserControl
{
public SimpleTriggerDisplay()
{
InitializeComponent();
this.Load += new EventHandler(SimpleTriggerDisplay_Load);
}
void SimpleTriggerDisplay_Load(object sender, EventArgs e)
{
lblDescription.Text = _trigger.Description;
lblGroup.Text = _trigger.Group;
lblName.Text = _trigger.Name;
if (_trigger.GetNextFireTimeUtc().HasValue)
{
lblNextFireTime.Text = _trigger.GetNextFireTimeUtc().Value.ToLocalTime().ToString();
}
else
{
lblNextFireTime.Text = "Unknown";
}
if (_trigger.GetPreviousFireTimeUtc().HasValue)
{
lblPreviousFireTime.Text = _trigger.GetPreviousFireTimeUtc().Value.ToLocalTime().ToString();
}
else
{
lblPreviousFireTime.Text = "Unknown";
}
lblRepeatCount.Text = _trigger.RepeatCount.ToString();
lblRepeatInterval.Text = _trigger.RepeatInterval.ToString();
}
public SimpleTriggerDisplay(SimpleTrigger trigger)
: this()
{
_trigger = trigger;
}
private SimpleTrigger _trigger;
}
}

+ 120
- 0
ClickForensics.Quartz.Manager/SimpleTriggerDisplay.resx View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

Loading…
Cancel
Save