在CC.net配置中使用自定义任务

时间:2012-07-16 16:36:19

标签: cruisecontrol.net

我为Cruise Control .net创建了以下自定义任务,但是我找不到如何将自定义任务添加到项目配置的单一参考。有没有人有一个如何在cc.net中添加对自定义任务的引用的有用示例?

(以下是我的新任务)

public class RestoreDb : TaskBase
{
    #region Parameters

    [Required]
    public string ServerName { get; set; }
    [Required]
    public string DbName { get; set; }

    public string BackupFileName { get; set; }

    #endregion

    protected override bool Execute(ThoughtWorks.CruiseControl.Core.IIntegrationResult result)
    {
        bool returnResult = false;
        try
        {
            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder();
            connectionStringBuilder.IntegratedSecurity = true;
            connectionStringBuilder.DataSource = ServerName;
            SqlConnection connection = new SqlConnection(connectionStringBuilder.ToString());
            connection.Open();

            Server server = new Server(new ServerConnection(connection));

            if (server.Databases[DbName] != null)
            {
                Log.Info("Dropping existing " + DbName + " on " + ServerName);
                server.Databases[DbName].Drop();
            }
            else
            {
                Log.Info(DbName + " on " + ServerName + " doesn't exist.");
            }

            Log.Info("Restoring " + DbName + " on " + ServerName);
            Database newDb = new Database(server, DbName);

            Restore rs = new Restore();
            rs.NoRecovery = false;

            FileInfo fi = new FileInfo(server.Settings.BackupDirectory + "\\" + BackupFileName);
            rs.Devices.AddDevice(fi.FullName, DeviceType.File);
            rs.Database = DbName;
            rs.Action = RestoreActionType.Database;
            rs.ReplaceDatabase = true;

            DataTable fileContents = rs.ReadFileList(server);
            string originalDbName = fileContents.Rows[0][0].ToString();
            string originalLogFileName = fileContents.Rows[1][0].ToString();
            rs.RelocateFiles.Add(new RelocateFile(originalDbName, 
            string.Format(@"C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\{0}.mdf", DbName)));

            rs.RelocateFiles.Add(new RelocateFile(originalLogFileName,
            string.Format(@"C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\{0}_1.ldf", DbName)));

            rs.SqlRestore(server);
            Log.Info("Restoring done.");
            returnResult = true; // success!
        }
        catch (Exception ex)
        {
            Log.Error(ex);
            returnResult = false;
        }
        return returnResult;
    }
}

2 个答案:

答案 0 :(得分:1)

你没有提到你正在使用的版本,所以我在假设用户将使用更新的版本时回答这个问题。我根据开发 1.8.3.0

的自定义任务的经验构建了这个

您可以在此处找到一些 来创建和使用http://www.cruisecontrolnet.org/projects/ccnet/wiki/DevInfo_MakingPlugins

编辑:我想请注意,所提供链接上的CruiseControl.NET文档已经更新,现在包含了大部分信息。

但是,这个文档的重量相当轻,并没有涵盖您最终会在尝试创建自己的任务时遇到问题的主题范围。

这个过程,就像我可以说的那样;

  • 您的自定义任务项目需要引用以下程序集,这些程序集可以在根CruiseControl.NET服务器文件夹中找到。

    • NetReflector.dll
    • ThoughtWorks.CruiseControl.Core.Dll
    • 您引用的任何其他程序集,不属于.NET 3.5 Framework
  • 构建自定义任务时,您需要使用Reflector属性标记要公开的任何类或属性,以使它们在ccnet.config中可用

  • 为了让CruiseControl.NET使用您的自定义库,您需要使用以下约定命名程序集:ccnet.WhateverYouWantHere.plugin.dll

  • 您需要将此程序集放在CruiseControl.NET Server文件夹中。

    • 如果您通过在ccnet.exe.config中为PluginLocation提供值来设置插件目录,则需要将程序集放在那里。
    • 您在项目中引用的任何尚未在CruiseControl.NET服务器文件夹中的程序集也需要添加到服务器或插件文件夹中
namespace MyTasks
{
    [ReflectorType("MyCustomTask")]
    public class MyCustomTaskClass : ITask 
    {
        [ReflectorProperty("MyCustomTaskProperty")]
        public string CustomProperty { get; set; }

        public string MyInternalPublicProperty { get; set; }

        public void Run(IIntegrationResult result){}
    }
}

注意:该属性的名称和您向ccnet.config公开的名称不必匹配。

为了引用创建的任务,标签符等,您只需使用Reflector属性中提供的字符串。

<project>
    <tasks>
        <MyCustomTask MyCustomTaskProperty="This is an example"/>
    </tasks>
</project>

如果您尝试使用此代码,并在标记中添加对MyInternalPublicProperty的引用,则无效:

<project>
    <tasks>
        <MyCustomTask MyInternalPublicProperty="This is will throw an exception in the service and not reload the ccnet config until the invalid content is removed from the config"/>
    </tasks>
</project>

这是因为你没有使用它自己的[ReflectorProperty()]属性来装饰属性。

答案 1 :(得分:0)

所以我基本上把它扔了,因为没有任何示例如何将自定义任务添加到cc.net配置。下面是我写的powershell脚本,它完成了相同的步骤。

$ServerName = 'servernamehere';
$DatabaseName = 'newDbNameHere';
$BackupFile = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Backup\backupFileHere.bak';
if($args[0])
{
    $ServerName = $args[0];
}
if($args[1])
{
    $DatabaseName = $args[1];
}
if($args[2])
{
    $BackupFile = $args[2];
}

[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended")
try 
{
    $Server = new-object ("Microsoft.SqlServer.Management.Smo.Server") $ServerName

    If ($Server.Databases.Contains($DatabaseName))
    {
        write-host "Dropping existing " $DatabaseName " on " $ServerName;
        #$Server.Databases[$DatabaseName].SetOffline();
        $Server.Databases[$DatabaseName].Drop();
    }
    else
    {
        write-host $DatabaseName " on " $ServerName " doesn't exist.";
    }
    $Database = new-object ("Microsoft.SqlServer.Management.Smo.Database") ($Server, $DatabaseName);

    $restore = new-object ('Microsoft.SqlServer.Management.Smo.Restore');
    $restore.NoRecovery = $false;

    $fil=new-object "Microsoft.SqlServer.Management.Smo.BackupDeviceItem";
    $fil.DeviceType='File';
    $fil.Name= $BackupFile;
    $restore.Action="Database";
    $restore.Devices.Add($fil);
    $restore.Database=$DatabaseName;
    $restore.ReplaceDatabase = $true;

    #retrieving the backup file's original database values so we can replace them
    $FileContents = $restore.ReadFileList($Server);
    $originalDbName =  $FileContents.Rows[0][0].ToString();
    $originalLogFileName = $FileContents.Rows[1][0].ToString();

    #replacing the bak files original file names with the new file names
    $mdf = new-object "Microsoft.SqlServer.Management.Smo.RelocateFile" ($originalDbName,
        "C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\$DatabaseName.mdf");
    $restore.RelocateFiles.Add($mdf);
    $ldf = new-object "Microsoft.SqlServer.Management.Smo.RelocateFile" ($originalLogFileName,
        "C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\$DatabaseName_Log.mdf");
    $restore.RelocateFiles.Add($ldf);


    write-host "Restoring database $DatabaseName  on  $ServerName from file $BackupFile";

        $restore.SqlRestore($Server);
        write-host "Restore Complete";
}
catch [System.Exception] {
  # $_ is set to the ErrorRecord of the exception
  $currentException = $_.Exception;
  write-host "Root Exception: " $currentException.Message;
  While($currentException.InnerException)
  {
    $currentException = $_.Exception.InnerException;
    write-host "Inner Exception: " $currentException.Message;
  }
  write-host "Restore Failed.";
  exit 0; #failure
}    
exit 1;