How to access a list in a website from a timer job - sharepoint

I'm creating a timer Job. And i have to access some lists which are in my solution stored in the site : "http://server:9090/sites/thesite"
For the moment, in my Timer Job i use this :
SPWebApplication webApplication = this.Parent as SPWebApplication;
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
SPList ParametresTech = contentDb.Sites["sites/thesite"].RootWeb.Lists[Constantes.Listes.PARAMETRES_TECHNIQUES.Name];
The problem i'm facing here is that i'm in my development environnement, and i don't know what will be the url of the site they will use to deploy the solution in production.
So is there a way to get to the list without knowing the name of the site ?
Thanks
EDIT :
That's how the timer job is activated :
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
string ListJobName = "SAPToSQL";
SPSite site = properties.Feature.Parent as SPSite;
// make sure the job isn't already registered
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == ListJobName)
job.Delete();
}
// install the job
TimerJobSAPToSP listLoggerJob = new TimerJobSAPToSP(ListJobName, site.WebApplication);
SPHourlySchedule schedule = new SPHourlySchedule();
schedule.BeginMinute = 0;
schedule.EndMinute = 59;
listLoggerJob.Schedule = schedule;
listLoggerJob.Update();
}

I would definitely identify the site collection using the feature ID that creates the timer job rather than by URL. Not only does this give you flexibility in naming sites, it also allows you to process multiple site collections that have each subscribed to the job.
I wrote the following utility method to collect the site collections for a timer job:
public static List<Guid> GetSiteIDs(SPWebApplication webApplication, Guid featureId)
{
List<Guid> ids = new List<Guid>();
foreach (SPSite site in webApplication.Sites)
{
try
{
if (SPSite.Exists(new Uri(site.Url))
&& null != site.Features[featureId])
{
try
{
ids.Add(site.ID);
}
catch (Exception ex)
{
// Handle Exception
}
}
}
finally
{
site.Dispose();
}
}
return ids;
}
In the featureId parameter, I pass a constant that I declare in my job definition class.
For more information see: Scope of a feature activated Custom Sharepoint-Timer Job

Related

SP2013 TimerJob constructor SPServer parameter

I have a timer job and I am trying to run this timer job on specific server, below is the code I am trying to use to compare server name and creating instance of timer job on FeatureActivated event. I have no idea how to do this. Please help me and correct me if I am doing it totally wrong.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
// Get an instance of the SharePoint farm.
//SPFarm farm = SPFarm.Local;
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
// Remove job if it exists.
DeleteJobAndSettings(webApp);
var serverName = SPServer.Local.DisplayName;
if (string.Equals("sp2013", serverName, StringComparison.OrdinalIgnoreCase))
{
// Create the job.
MyReportNew job = new MyReportNew(webApp, SPServer.Local);
//Other code
}
}
Firstly, you need to use SPServerJobDefinition class.
Secondly, retrieve SPServer object from SPFarm.Local.Servers collection.
For example:
public class CustomJob : SPServerJobDefinition
{
public CustomJob()
: base()
{
}
public CustomJob(string jobName, SPServer server)
: base(jobName, server)
{
this.Title = jobName;
}
public override void Execute(SPJobState state)
{
// do stuff
}
}
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
// Get an instance of the SharePoint farm.
SPFarm farm = SPFarm.Local;
// Remove job if it exists.
DeleteJobAndSettings(webApp);
// Create the job.
MyReportNew job = new MyReportNew("MyJobName", farm.Servers["sp2013"]);
//Other code
}

Sharepoint 2010 event receiver and workflow not starting

I created an event receiver that should trigger a SharePoint designer workflow, however this never happens. This part of the code never evaluates to true for the guid and workflow association: if (association.BaseId == workflowGuid). I am a bit stumped and not quite sure why it's not working. Any insight would be appreciated...and my code is below. Basically when an item is added to my list, it should trigger my Sharepoint designer workflow but this never happens and I can manually start the workflow fine.
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
startWF(properties);
}
private void startWF(SPItemEventProperties properties)
{
try
{
//bool startWF = false;
string strWorkflowID = "{c66ff94f-ba7c-4495-82fe-e73cdd18bad9}";
//string statusVal = properties.AfterProperties["eRequest Division"].ToString();
SPListItem li = properties.ListItem;
//using (SPWeb web = li.Web)
using (SPWeb web = properties.OpenWeb())
{
using (SPSite site = web.Site)
{
SPWorkflowManager mgr = site.WorkflowManager;
SPList parentList = li.ParentList;
//SPList list = web.Lists["Charitable and Political"];
SPWorkflowAssociationCollection associationCollection = parentList.WorkflowAssociations;
LookUpAndStart(li, mgr, associationCollection, "{c66ff94f-ba7c-4495-82fe-e73cdd18bad9}");
}
}
}
catch (Exception ex)
{
}
}
private static void LookUpAndStart(SPListItem listItem, SPWorkflowManager mgr, SPWorkflowAssociationCollection associationCollection, string workflowID)
{
foreach (SPWorkflowAssociation association in associationCollection)
{
Guid workflowGuid = new Guid(workflowID);
//if (association.Name.ToLower().Equals(workflowGuid))
//if (association.BaseId == workflowGuid)
//if (association.BaseId.ToString("B").Equals(workflowGuid))
if (association.BaseId == workflowGuid)
{
string data = association.AssociationData;
SPWorkflow wf = mgr.StartWorkflow(listItem, association, data, true);
break;
}
}
}
}
}
In my case the following was the problem.
Declarative workflows will not start automatically if the following conditions are true:
The Windows SharePoint Services Web application runs under a user's domain account.
The user logs in by using this domain account.
The site displays the user name as System Account.

EventReceiver to Create folder sharepoint 2010

I have this event receiver c# class that I am trying to implement on a Sharepoint site. It did not work. I have deployed it from visual studio 2010 after it was build ok. Does anyone see what is the problem? Is the code ok? or is the problem on the SP? Thank you.
- here is the new code
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace EventReceiverCFolder.EventReceiver1
{
/// <summary>
/// List Item Events
/// </summary>
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item is being added.
/// </summary>
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
if (properties.ListTitle == "CF") // list where the item was added
{ // if item was added to this list then create a folder on - Dlib - list
UpdateFolder(properties);
}
}
catch (Exception ex)
{
properties.Status = SPEventReceiverStatus.CancelWithError;
properties.ErrorMessage = ex.Message;
properties.Cancel = true;
}
}
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("DLib"); // this is doc Library where the new folder will be created
//note that we are creating a list item, not a folder - a folder IS a list item
SPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (createdFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
finally { }
}
}
}
Don't do this: SPUser privilegedAccount = properties.Web.AllUsers[#"SHAREPOINT\SYSTEM"];
Read up on using SPSecurity.RunWithElevatedPrivileges. See the MSDN documentation here.
Also don't do a using (SPSite... and inside the using block you try to get the web via SPContext.Current - that web won't be elevated anymore.
The correct way is something along these lines (I didn't try this, so it' just to give you an idea where you are headed):
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("ListTitle"); //is that really the list title?
//note that we are creating a list item, not a folder - a folder IS a list item
SSPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (newFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
Also try to debug your code, set breakpoints etc.
I had to get folder name like this:
string foldername = Convert.ToString(properties.AfterProperties["Title"]);
Did you try to debug it? try to debug and tell us what error you are getting.
BUT before you debug first use sharepoint manager to see if your event receiver is attached properly.
If you dont know how to debug sharepoint event receiver then please see this

Checking permissions of a user with a site collection

I want to check whether a user has permissions to a site collection. But i dono how to use SPSite.DoesUserHavePermissions().
What is SPReusableAcl? How can i get it for checking the permissions of the user?
Doesn't the MSDN article (SPWeb.DoesUserHavePermissions Method (String, SPBasePermissions)) help you? The example code can be used to check whether the user has access to a site collection:
using System;
using Microsoft.SharePoint;
namespace Test
{
class Program
{
static void Main(string[] args)
{
using (SPSite site = new SPSite("http://localhost"))
{
using (SPWeb web = site.OpenWeb())
{
// Make sure the current user can enumerate permissions.
if (web.DoesUserHavePermissions(SPBasePermissions.EnumeratePermissions))
{
// Specify the permission to check.
SPBasePermissions permissionToCheck = SPBasePermissions.ManageLists;
Console.WriteLine("The following users have {0} permission:", permissionToCheck);
// Check the permissions of users who are explicitly assigned permissions.
SPUserCollection users = web.Users;
foreach (SPUser user in users)
{
string login = user.LoginName;
if (web.DoesUserHavePermissions(login, permissionToCheck))
{
Console.WriteLine(login);
}
}
}
}
}
Console.ReadLine();
}
}
}
In the sample code above you would just have to change your Site URL and the Variable permissionToCheck. SPBasePermissions has a lot of possible permissions to check against, you can see the enumeration here (SPBasePermissions Enumeration).
Actually there are a lot of tutorials on how to check some user's permissions and you are not limited to DoesUserHavePermissions, see the following Google Search.
As usual, the MSDN examples provide nice textbook examples that do not always apply to real-life scenarios.
In the context of an application page running on SharePoint 2010, from what i understand this code needs to be wrapped in a call to RunWithElevatedPrivileges and even then, as my comment implies, it seems there is an implied catch-22 in the requirements. This works for me (the LoginName is just the FBA username or "domain\user" for AD user for the site - in our case an e-mail address is used):
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(siteCollectionUrl))
{
foreach (SPSite siteCollection in elevatedSite.WebApplication.Sites)
{
using (SPWeb elevatedWeb = siteCollection.OpenWeb())
{
bool allowUnsafeUpdates = elevatedWeb.AllowUnsafeUpdates;
bool originalCatchValue = SPSecurity.CatchAccessDeniedException;
SPSecurity.CatchAccessDeniedException = false;
try
{
elevatedWeb.AllowUnsafeUpdates = true;
// You can't verify permissions if the user does not exist and you
// can't ensure the user if the user does not have access so we
// are stuck with a try-catch
SPUser innerUser = elevatedWeb.EnsureUser(loginName);
if (null != innerUser)
{
string splogin = innerUser.LoginName;
if (!string.IsNullOrEmpty(splogin) && elevatedWeb.DoesUserHavePermissions(splogin, SPBasePermissions.ViewPages))
{
// this user has permissions; any other login - particularly one that
// results in an UnauthorizedAccessException - does not
}
}
}
catch (UnauthorizedAccessException)
{
// handle exception
}
catch (Exception)
{
// do nothing
}
finally
{
elevatedWeb.AllowUnsafeUpdates = allowUnsafeUpdates;
// reset the flag
SPSecurity.CatchAccessDeniedException = originalCatchValue;
}
}
}
}
});
SPSite.DoesUserHavePermissions(SPReusableAcl, SPBasePermissions);

Problem Activating Sharepoint Timer Job

I have created a very simple sharepoint timer job. All i want it to do is iterate through a list and update each list item so that it triggers an existing workflow that works fine. In other words all i am trying to do is work around the limitation that workflows cannot be triggered on a scheduled basis. I have written a class that inherits from SPJobDefinition that does the work and i have a class that inherits from SPFeatureReceiver to install and activate it. I have created the feature using SPVisualdev that my coleagues have used in the past for other SP development.
My Job class is below:
public class DriverSafetyCheckTrigger : SPJobDefinition
{
private string pi_SiteUrl;
public DriverSafetyCheckTrigger(string SiteURL, SPWebApplication WebApp):base("DriverSafetyCheckTrigger",WebApp,null, SPJobLockType.Job)
{
this.Title = "DriverSafetyCheckTrigger";
pi_SiteUrl = SiteURL;
}
public override void Execute(Guid targetInstanceId)
{
using (SPSite siteCollection = new SPSite(pi_SiteUrl))
{
using (SPWeb site = siteCollection.RootWeb)
{
SPList taskList = site.Lists["Driver Safety Check"];
foreach(SPListItem item in taskList.Items)
{
item.Update();
}
}
}
}
}
And the only thing in the feature reciever class is that i have overridden the FeatureActivated method below:
public override void FeatureActivated(SPFeatureReceiverProperties Properties)
{
SPSite site = Properties.Feature.Parent as SPSite;
// Make sure the job isn't already registered.
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == "DriverSafetyCheckTrigger")
job.Delete();
}
// Install the job.
DriverSafetyCheckTrigger oDriverSafetyCheckTrigger = new DriverSafetyCheckTrigger(site.Url, site.WebApplication);
SPDailySchedule oSchedule = new SPDailySchedule();
oSchedule.BeginHour = 1;
oDriverSafetyCheckTrigger.Schedule = oSchedule;
oDriverSafetyCheckTrigger.Update();
}
The problem i have is that when i try to activate the feature it throws a NullReferenceException on the line oDriverSafetyCheckTrigger.Update(). I am not sure what is null in this case, the example i have followed for this is this tutorial. I am not sure what I am doing wrong.
I ran your code in a console application and got the following exception when calling .Update()
"DriverSafetyCheckTrigger cannot be deserialized because it does not have a public default constructor"
Maybe that will help?
I have similar code that is working in one of my Feature Receivers:
string jobName = "MyJobDefinition";
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == jobName)
{
job.Delete();
}
}
SPDailySchedule schedule = new SPDailySchedule();
schedule.EndHour = 2;
schedule.EndMinute = 59;
schedule.EndSecond = 59;
SPJobDefinition jobDefinition = new MyJobDefinition(jobName, site.WebApplication);
jobDefinition.Schedule = schedule;
jobDefinition.Update();
I wonder if your problem is with the schedule. Try setting BeginMinute and maybe also BeginSecond. You could also try setting the End values in conjunction with or instead of the Begin values.

Resources