I'm back again with another SharePoint question!
I have an application that returns a list of features on the local SharePoint farm. But the issue is that it seems to return them as 'Online' whether or not they are activated.
For example, this feature would still show up in my app as 'Online' even though it is not activated:
The code I am using currently is as follows:
foreach (SPFeatureDefinition featureDefinition in featureCollection)
{
if (featureDefinition.Scope.Equals(scopeSelect))
{
string featureName = featureDefinition.DisplayName;
XElement newItem = new XElement("Item", featureName);
XElement itemStatus = new XElement("Item", featureDefinition.Status);
infoTree.Add(newItem);
infoTree.Add(itemStatus);
}
}
}
The issue is that featureDefinition.Status always returns 'Online' regardless of the actual status of the feature. This leads me to believe I am doing something wrong, or the .Status property isn't actually what I am looking for.
Is there another property I can use that would set me on the right track?
Any guidance/suggestions will be most appreciated!
EDIT:
Just as an aside, an IIS reset does not have any effect on it returning a different status.
Yes, the .Status property will tell you the status of the Definition, but no the activation status of the feature at a specific scope. You have a to understand a bit about features for this: A feature definition is just the template - you activate an instance of the feature at specific level (farm, webapp, site, web) - hence you can't check the status of the definition, but need to check whether the instance of the feature exists at the specific scope.
To check the feature status via PowerShell you can just use Get-SPFeature as described here. As you can see, all the code is doing is calling Get-SPFeature and if it returns something for a specific scope the feature is activated. You can do the same thing in C#.
So when you want to check whether a feature is activated e.g. on site scope you can just iterate over SPSite.Features, when you find the feature you know it is activated. The Powershell commandlet isn't doing anything else.
You want to check a farm feature, so you can check the collection at SPWebService.ContentService.Features to check for activated farm features. See another example of a PowerShell script (almost looks like C#) here.
Related
I am searching for the possibility to open default property dialogues for particular Windows objects, like:
the property dialogue for a particular service in services.msc
the property dialogue for a particular scheduled taks in taskschd.msc
etc.
I do not want to interact with that dialogues or change any of the properties. I just want to open them to give the user direct access to a single items properties (instead of opening the listings (by calling the *.msc executables) in which the user has to search the object again).
I have already partially copied the dialogues functions into own forms and code for other purposes, by the way, but I want to give the user the option to open the default ones and make any changes directly.
Now, I have found some hints but I am stuck as there is always some crucial information missing:
1. Using so-called SnapIns of MMC (Microsoft Management Console)
There is this relatively new answer which uses VB code but I have no clue how I could use the MMC Automation Object Model in C# .NET Framework.
Furthermore, there is no clean and easy example/explanation of how to simply call an existing .msc process/list/window by usage of the Microsoft.ManagementConsole. Instead, there are several horrifying complex tutorials how to implement SnapIns into C#.
To be clear here: What I want to do is to reference a dll, go through some list (if necessary) and just call the properties dialogue.
2. COM invoke of old API
There is this old answer where someone recommends using invoke on an outdated ITaskScheduler class which does not solve the general dialogue call but at least the one for scheduled tasks. Perhaps it is also possible to use something similar for services, etc. - but, again, there is no clear example or explanation of how to implement this approach.
It's relatively simple.
Add a COM Reference to Microsoft Management Console 2.0.
Add the using MMC20 directive.
Create a new MMC20.Application object
Use the Application.Load() method to load a Snap-In (services.msc here)
The ActiveView of the Application Document contains the list of items: ListItems Property
Select a Node by name or Index and call the DisplaySelectionPropertySheet() method to show its Property pane
For example:
Note: setting mmcApp.UserControl = 1; leaves the Console open, otherwise it would close.
using MMC20;
// [...]
MMC20.Application mmcApp = new MMC20.Application();
mmcApp.UserControl = 1;
mmcApp.Load("services.msc");
var doc = mmcApp.Document;
var view = doc.ActiveView;
var node = view.ListItems.OfType<Node>().FirstOrDefault(n => n.Name == "Base Filtering Engine");
if (node != null) {
view.Select(node);
view.DisplaySelectionPropertySheet();
}
To enumerate the ListItems, use a standard loop or an extension method as shown above:
var nodes = view.ListItems;
foreach (MMC20.Node node in nodes) {
Console.WriteLine(node.Name);
}
Here's documentation on how to use the MMC SDK. It's a Win32 API, so you'll have to use COM, PInvoke, or other interop to use it.
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/mmc/microsoft-management-console-start-page#developer-audience
The C++ examples are probably more informative than the VB ones. The .h files are part of the windows sdk so you should be able to find the clsid and other constants that you need in there: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/mmc/using-c-with-the-mmc-2-0-automation-object-model
I have tried finding an answer to this question practically everywhere I could imagine, including here on StackOverflow. Unfortunately to no avail. So here it is.
I'm working on an Outlook Add-in (with Outlook 2021), and have developed some code that creates some ItemProperties specifically for use with that add-in. Now, when those properties are created, I can see them when I go to View->Settings->Advanced View Settings->Columns, as illustrated in the screenshot.
Screenshot of User-defined fields in Outlook
In some cases, though, I want to completely delete the properties. And as I know how to do that manually, as pointed out in the figure, I can't find out how to do that programmatically via C#. I have gone that far as to remove the properties from each mail containing that kind of property, like this:
IEnumerable<MailItem> listOfAssignedEmails = itemsToProcess.Where(
t => t.ItemProperties[MailExpiration.ExpirationDatePropertyName] != null);
foreach (MailItem email in listOfAssignedEmails)
{
// Note: The Delete() operation is deprecated. A more up-to-date method must be found.
email.ItemProperties[MailExpiration.ExpirationDatePropertyName].Delete();
email.Save();
}
... and yes, I know that the Delete() operation is deprecated; however, I couldn't find another method for removing the ItemProperty from the email (any suggestions are welcome).
Basically, the deletion of this Property is only going to be done very rarely (t. ex. if the user chooses to uninstall the Add-in. However, if there's any way to remove that property automatically, I would be happy to know.
Any suggestions will be greatly appreciated.
It is really a bad idea to remove a custom property from all emails that already have it: there is really no point since the user will never see them, but you will have to retouch (and thus change the last modified date) of a large number of emails.
Also note that named properties in MAPI are a finite resource - you can have at most 64k of them in a mailbox. Once a particular property mapping is used, you can never unmap it, even if there are no items that use that property.
Thirdly, doing anything Outlook related from an installer (rather than a VSTO addin) is a really bad idea - Windows installer runs in a service.
If you want to make sure the user no longer sees your custom fields as available properties in a view, you need to deal with the folder fields - they ar stored in a blob in a hidden (associated) message in that folder. OOM does not expose folder fields at all (if you don't count the AddToFolderFields parameter when calling UserProperties.Add). If using Redemption is an option (I am its author), it exposed RDOFolderFields object (accessible from RDOFolder2.FolderFields property) that allows to add or delete folder fields.
The list of properties shown on the screenshot belongs to the Folder.UserDefinedProperties property which returns a UserDefinedProperties object that represents the user-defined custom properties for the Folder object.
Use the ItemProperties.Remove method removes an object from the collection (from an item).
Use the ItemProperties property to return the ItemProperties collection. Use ItemProperties.Item(index), where index is the name of the object or the numeric position of the item within the collection, to return a single ItemProperty object.
Background: I have developed a couple of SharePoint 2010 web parts using Visual Studio with custom properties. I have also been able to set these properties with code so that they persist. I also know that SharePoint users can personalize pages & web parts with their own property values etc.
Question: Is it possible to set up a property that is always only user-specific?
In other words, I want my web part to have a property that starts out blank and is assigned a value once a user performs an action within the web part, but that value is specific to that user. Other users viewing the page would need to perform that action to get their own value. I would like for this to happen without the users having to manually personalize the page.
I tried setting attributes:
Personalizable( PersonalizationScope.User )
and later added
WebPartStorage( Storage.Personal )
and did some testing, but the value set by the first user always persisted to the second.
We haven't done a lot with personalization, so I'm really just curious if this is even possible.
You should be able to add an attribute [Personalizable(true)].
The WebPartStorage property (with Storage.Shared and Storage.Personal) is a holdover from the older API for SharePoint 2003, as documented here.
Take a look at Microsoft's walkthrough article here: Creating a Custom Web Part Editor in SharePoint 2010
The Web Part declares a private variable _tabList as a collection of TabData objects. This collection is wrapped through the TabList property. The property returns an empty collection if _tabList is null. The property is also marked Personalizable, to enable users to customize the tabs.
[...]
// Collection of tabs.
private List<TabData> _tabList;
// Property to hold the collection of tabs.
// Set the Personalizable attribute to true,
// to allow for personalization of tabs by users.
[Personalizable(true)]
public List<TabData> TabList {
get
{
if (this._tabList == null)
{
// Return an empty collection if null.
this._tabList = new List<TabData>();
}
return this._tabList;
}
set
{
this._tabList = value;
}
}
For more reading, check out Microsoft's documentation here: About Web Part Page personal and shared views
Notably, consider the following excerpt:
When a Web Part page is in personal page view, you:
Can usually view and modify the Layout and Appearance common Web Part properties, but not the Advanced ones. In some cases, the developer of a Web Part may decide not to display some or all common properties or you may not have permission to see them.
Can view and modify custom Web Part properties. In some cases, the developer of a Web Part may decide not to display some or all custom properties or you may not have permission to see them.
Can view and modify, but not delete, shared Web Parts with appropriate permission. Once you modify a shared Web Part, however, it becomes a personalized Web Part.
Can view and modify, but not delete, personalized Web Parts. The modified property values of these Web Parts apply only to you.
Can view, modify, and delete private Web Parts. These Web Parts only apply to you, no other users can see them, even in shared view.
By default, only Layout and Appearance properties are customized to the current user when editing a page in personal view. Custom properties are shared unless you explicitly make them personalizable.
I'm trying to test if items can be viewed by an anonymous user:
var anon = User.FromName("domain\\Anonymous");
if (item.Security.CanRead(anonymousUser))
return true;
But it always returns true, even when I know that for particular items, they must have a certain role to view it, as I can see from the access viewer:
The responsible crawler -which actually executes ComputeFieldValue code- is designed in such way to wrap this code in a SecurityDisabler. That is why it is not possible inside a computed field to verify whether has access to the field or not.
Sitecore does recommend to do the security check during the search (ootb) but indeed the TotalResults do not match if you do - which sucks ;)
If you would try to get security in the index - first try to find a solution for keeping the item security updated. E.g. if you would break inheritance somewhere, how would your index know what items to update? ...
I'm searching for a way to access the calendar and email inbox of another user (I can access my own calendar/email without any problems). Currently I can access the other inbox/calendar via lotus notes (I have enough rights). But I couldn't manage it to access the data programmatically.
I already listed all my views, but there was nothing appropriated.
private Domino.NotesDatabase db;
Object[] docColl = this.db.Views as Object[];
foreach (Object objView in docColl)
{
NotesView view = objView as NotesView;
this.WriteToLog(view.Name);
}
Any ideas, if this is possible and how?
Every Notes user's mail box is in a separate database.
So, first you have to get the database with
Domino.NotesDatabase db =
session.GetDatabase("yourServer", "UserMail.nsf", false);
and there you can access the calendar and email folders.
#Knut's answer gives you the basic information that you need, but I'd like to clarify it a bit: it has to be the hisServer (or herServer), not yourServer. Also, it will usually be "mail\hisShortname.nsf"), but that's not always the case. The point is that if you are trying to write generalized code, you have to look these things up in the Domino Directory.
If you're using a recent version of the Notes APIs, the best way to proceed is by using session.getDirectory(myServer) to get a NotesDirectory object. (It doesn't matter what server you use in this case, as long as the users are in the same Notes domain.) Here's the doc for the getDirectory method.
Once you have a handle to the Domino Directory, you need to look up information for the Person whose mail file you want to access. The formal documentation for the NotesDirectory class seems to be frustratingly hard to find online every time I search for it, so I can't link to that. The second example in the first section of this wiki page shows a call to the LookupNames method to retrieve information for a Person object, which is what you need to do. The two items that you want to retrieve are "MailServer" and "MailFile".