Pages

Search This Blog

Showing posts with label Timer Job. Show all posts
Showing posts with label Timer Job. Show all posts

Tuesday, February 11, 2014

Install Timer Jobs through Powershell in SharePoint

If you need to install Timer service through Powershell in SharePoint, you can make use of the below script. This script will install custom timer job in the defined web application. Fir the purpose of testing, this script also has a function to execute the timer job. This is very helpful if you wish to execute your job immediately after installing.

Copy below code and paste it in file with extension - .ps1




#__________________________Install SharePoint Timer Jobs___________________________________

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#                             VARIABLE DECLATRATION
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#

# Grab the web app URL from User
write-host "Enter the Web Application Url where you want to deploy the Timer service:"
[string]$webAppUrl = Read-Host

# Define here the Timer Job assembly name.
[string]$assemblyName = "TechPerspect.TimerJobs"

# Define here the Job Name
[string]$jobName = "TechPerspect Demo Timer Job"

# Define the class name here. (assembly name + class name of timer job)
$className = "TechPerspect.TimerJobs.DemoTimerJob"


# load the required assemblies
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint")
[void][reflection.assembly]::LoadwithPartialName("Microsoft.Office.Server")

# Stop further execution of an error occured anywhere in script
$ErrorActionPreference = "Stop"


#
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#                                 Functions
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#

# This methods restarts SharePoint Timer service (OWSTIMER)
function global:Restart-TimerServices
{
    # Restart timer services
    Write-Host "Restarting SharePoint Timer services"
    Stop-Service "SPTimerV4"
    Start-Service "SPTimerV4"
}

function global:Install-TimerJob
{
    Restart-TimerServices

    # Load job assembly
    [void][reflection.assembly]::LoadwithPartialName($assemblyName)
    # below call is commented however may be used in Powershell v3.0, since          
    # LoadwithPartialName is depreciated after powershell 2.0
    #[System.Reflection.Assembly]::Load("TechPerspect.TimerJobs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d8668901f3456325")

    $objSPSite = [Microsoft.SharePoint.SPSite]$webAppUrl
    $objWebApplication = $objSPSite.WebApplication
    # search for the Job
    $objTimerJobInstance = $objWebApplication.JobDefinitions | ? { $_.Name -like $jobName }

       # Delete the job instance if already exists
       if ($objTimerJobInstance)
    {
        Write-Host "Job [" $objTimerJobInstance.Name "] already exists. Deleting..."
       $objTimerJobInstance.Delete()
       }
      
       # Initlize new instance of timer job
    # Note that the argument List should be same, which you have defined in your 
    # timer service code for invoking the service.
    # Argument list could contain 1, 2, 3 params depending upon constructor used 
    # in your timer code
    $objTimerJobInstance = new-object $className -ArgumentList $jobName,$objWebApplication
      
       # Create a Daily Schedule
    $sched = new-object Microsoft.SharePoint.SPDailySchedule
    # setting the hour to execute at 0100 AM to 0200 AM
    $sched.BeginHour = 1
    $sched.EndHour = 2
    $objTimerJobInstance.Schedule = $sched
    $objTimerJobInstance.Update()

       # Set the schedule to the timerjob object and save the job schedule
    $objTimerJobInstance.Schedule = $sched
    $objTimerJobInstance.Update()
   
    # Dispose site
    $objSPSite.Dispose()

    Restart-TimerServices
}



#This method will execute the Timer Job.(helpful when testing the timer jobs)
function global:Execute-TimerJob
{


    # Open site
    $objSPSite = [Microsoft.SharePoint.SPSite]$webAppUrl
    $objWebApplication = $objSPSite.WebApplication

    # Content DB to execute job on
    $contentDB = $objWebApplication.ContentDatabases[0]

    # Search for the Job
    $objTimerJobInstance = $objWebApplication.JobDefinitions | ? { $_.Name -like $jobName }

    if ($objTimerJobInstance)
    {
        Write-Host "Executing Timer Job [" $objTimerJobInstance.Name "]..."
        $objTimerJobInstance.Execute($contentDB.Id)
        Write-Host "Job Executed successfully!"
    }
    else
    {
        Write-Host "Job [" $jobName "] not found"
    }
    # Dispose site
    $objSPSite.Dispose()
}



#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#                                        MAIN
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#


Install-TimerJob

# If you want to test the timer service, uncomment the below method call
#Write-Host "Executing the Timer Job..."
#Execute-TimerJob


Thursday, March 22, 2012

Access denied on SPJobDefinition RunNow()

Recently I faced strange issue while executing a timer service through my web part. Since it was possible in MOSS 2007, but I know SharePoint 2010 does not support executing any timer job through code. I have already written a solution for setting up the property : RemoteAdministratorAccessDenied. This property allows modification of the SPPersistedObject from content web applications.  The post can be viewed at: http://www.directsharepoint.com/2011/04/access-denied-while-activating-feature.html. However when I tried to execute the timer, It gave an error as:

"Operation is not valid due to the current state of the object"

To resolve this, I cleared the HttpContext.Current property to null as:


SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite elevatedSite = new SPSite("Site URL"))
                    {
                        foreach (SPJobDefinition job in  elevatedSite.WebApplication.JobDefinitions)
                        {
                            if (job.Title.Equals("Your job name") && job.Status == SPObjectStatus.Online)
                            {
                                HttpContext.Current = null;
                                job.RunNow();
                                break;
                            }
                        }
                    }
                });



Thursday, November 17, 2011

Solution Deployment Stuck Retracting OR Deploying in SharePoint 2007


Few steps that you should see for this problem

stsadm –o enumdeployments

This will present some XML spew.  It’s easily readable, so find your solution name and get the job id. Then cancel the deployment…

stsadm –o canceldeployment –id <id>


This command will cancel the timer job and you will be able to retract or redeploy your solution.

Thursday, July 28, 2011

System.ServiceModel.EndpointNotFoundException in OWSTIMER.EXE

Problem:

This is a very common issue in SharePoint installation when you see this screen after every 5 minutes on SharePoint Server





Visual Studio Just-In-Time Debugger
An unhandled exception ('System.ServiceModel.EndpointNotFoundException') occurred in OWSTIMER.EXE [5220].
The Just-In-Time debugger was launched without necessary security permissions. To debug this process, the Just-In-Time debugger must be run as an Administrator. Would you like to debug this process?


Resolution:

Start Forefront end service from services management window

Type services.msc in Run Command 
Start the forefront identity manager service 




Saturday, February 5, 2011

Dump SharePoint Lists Data into SQL Server Tables using SqlBulkCopy

In one of our projects it is required to clean and normalize SharePoint Data and dump that data into SQL server so that any third party can consume that data for reporting purposes. For that we created a timer job that runs every night and does the job....  Here is the approach that we took for implementation


Create a SharePoint Timer job  and add these two references

using System.Data;
using System.Data.SqlClient;



class DatabaseDump : SPJobDefinition
    {
        // No Argument Constructor (required for the system internal operation)
        public DatabaseDump()
        {
        }

        public DatabaseDump(string JobName, SPWebApplication objWebApplication)
            : base(JobName, objWebApplication, null, SPJobLockType.Job)
        {

        }


        public override void Execute(Guid targetInstanceId)
        {

            SPWebApplication currentWebApplication = this.WebApplication;
            try
            {
                using (SPSite currentSite = currentWebApplication.Sites[0])
                {
                    //todo:call export program
                    ExportData(currentSite.Url);
                 }
            }
            catch (Exception ex)
            {
                //exception handling here
            }
        }
    }


Step 2 : Create a function for ExportData

public void ExportData(string SpSiteURL)
        {
            DataTable SourceTable;
            DataTable UserMappingTable;
            DataRow dr;
            DataRow drMapping;
            string tableName;
            string connectionString;
            SPQuery query;
            try
            {
                connectionString = "SQL SERV ER CONNECTION STRING";
                if (!string.IsNullOrEmpty(connectionString))
                {
                    using (SqlConnection connection = new SqlConnection(connectionString))
                    {
                        connection.Open();
                        if (connection != null)
                        {
                            using (SPSite objSite = new SPSite(SpSiteURL))
                            {
                                using (SPWeb currentWeb = objSite.OpenWeb())
                               {
                                    //first of all get the data of all lists in the system
                                    foreach (SPList DFList in currentWeb.Lists)
                                    {
                                        try
                                        {
                                            if (!DFList.Hidden)
                                            {
                                                foreach (SPView view in DFList.Views)
                                                {
//we created a view for the data to be exported but default view can also be used here

                                                    if (view.Title =="Reports View")
                                                    {
                                                        SourceTable = DFList.GetItems(view).GetDataTable();
                                                        if (SourceTable != null)
                                                        {
                                                            //clean table name if required
                                                            tableName = CleanupSQLOBjectName(DFList.Title);
                                                        //drop and create new table first or if you don't want to do this then truncate it first                  
                                       CreateTable(connection, tableName, SourceTable);
                                                            BulkCopy(connection, tableName, SourceTable);
                                                        }
                                                        else
                                                        {
                                                            //no data in this list
                                                            //we need to truncate the existing data for this list now
                                                            tableName = CleanupSQLOBjectName(DFList.Title);
                                                            TruncateTable(connection, tableName);

                                                        }
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                          //handle exception here
                                        }
                                    }
        }




   private string CleanupSQLOBjectName(String SQLObjectName)
        {
            StringBuilder tempSb = new StringBuilder(SQLObjectName);
            tempSb = tempSb.Replace("/", "_");
            //these are two types of dashes
            tempSb = tempSb.Replace("–", "_");
            tempSb = tempSb.Replace("-", "_");
            tempSb = tempSb.Replace("(", "_");
            tempSb = tempSb.Replace(")", "_");
            tempSb = tempSb.Replace(" ", "_");
            tempSb = tempSb.Replace("_x0020_", "_");
            tempSb = tempSb.Replace("_x002f_", "_");
            tempSb = tempSb.Replace("__", "_");
            if (tempSb.Equals("group"))
            {
                tempSb.Replace("group", "group_1");//"Group" is a reserved word
            }
            return tempSb.ToString();
        }




private void CreateTable(SqlConnection connection, string tableName, string[] columns, string[] dataTypes)
        {
            StringBuilder strBuilder;
        
            SqlCommand cmd;

            //first drop this table
            DropTable(connection, tableName);


            //now we need to create table
            strBuilder = new StringBuilder();
            strBuilder.Append("CREATE TABLE " + tableName + " (");

            for (int i = 0; i < columns.Length; i++)
            {
                strBuilder.Append("[" + columns[i] + "] " + dataTypes[i] + ", ");
            }

            strBuilder.Append(")");


            cmd = new SqlCommand();

            cmd.Connection = connection;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = strBuilder.ToString();
            cmd.ExecuteNonQuery();
        }





   private void BulkCopy(SqlConnection connection, string tableName, DataTable SourceTable)
        {
            //now copy the data
            using (SqlBulkCopy bulkcopy = new SqlBulkCopy(connection))
            {
                //Set destination table name
                //to table previously created.
                bulkcopy.DestinationTableName = tableName;
                bulkcopy.WriteToServer(SourceTable);
            }
        }


This will update all the data of sharepoint lists in a SQL server database. You can add code to normalize lookup columns, multivalue columns etc and can also extend it to create child tables for lookup data..

Let us know if somebody require any assistance in extending this code.