Domanda

I was asked to create a phone list of employees into our company SharePoint website that automatically updates whenever new users are added into our active directory.

I've researched a few things such as UPS(user profile sync) but from my understanding, this pulls the whole profile of every user from the active directory where I am only wanting the first/last name and phone number.

È stato utile?

Soluzione

I'm sure there are many ways to do this, but thought I'd share parts of my Powershell solution to do exactly that. Maybe it will give you some ideas even if you use different language. I wronte this for 2010, so I'm not using REST calls or anything newer that could be used in SP2013/2016

We have an online employee list that is populated through changes in AD - it's separate from the SharePoint user lists.

I created a custom list with the usual fields needed: first, last name, department, phone.... whatever you need. I also included a single-line text field for the SID of the AD user.

My powershell is scheduled to run every morning, so it will pick up any changes/deletions. It is not running on the SharePoint server so it uses basic CAML/list web services.

The important pieces: Note, there are < and > building the CAML that don't show up here, so I replaced them with ( and ) so this makes sense. I might have missed something, so double check if I have to many opening or closing { }

Import the AD module

 Import-Module ActiveDirectory -ErrorAction SilentlyContinue

I get the current list into a hash to make it easier to compare it to AD

    $WebUrl = "https://xxxx"
    $service = New-WebServiceProxy -Uri ($WebUrl + "/_vti_bin/lists.asmx?WSDL")  -Namespace SpWs  -UseDefaultCredential 
    #Employee Phone List           
    $listName = "{a guid}" # or even a list name   

 # Retrieve Current 'Employee' entries in the Employee Phone List
        $xmlDocToday = new-object System.Xml.XmlDocument
        $query = $xmlDocToday.CreateElement("Query")
        $selection = "(Where)(Eq)(FieldRef Name = 'PhoneType' /)(Value Type = 'Choice')Employee(/Value)(/Eq)(/Where)"           
        $query.set_InnerXml($selection)

        $viewFields = $xmlDocToday.CreateElement("ViewFields")
        $viewFields.set_InnerXml("(FieldRef Name='ID' /)(FieldRef Name='SID' /)(FieldRef Name='FirstName' /)(FieldRef Name='Department' /)(FieldRef Name='Account' /)(FieldRef Name='WorkPhone' /)(FieldRef Name='FullLastName' /)") 

        $queryOptions = $xmlDocToday.CreateElement("QueryOptions") 

        [System.Xml.XmlNode]$ndReturn = $service.GetListItems($listName, $null, $query, $viewFields, "1000", $queryOptions, $null)

 # Build hash table of all employees for lookup
# if account is empty, use 'generic'
     $eHash = @{}
    foreach ($row in $ndReturn.data.row) {

        $employee = New-Object PSObject
        $employee | Add-Member -type NoteProperty -name ID -value $row.ows_ID
        $employee | Add-Member -type NoteProperty -name SID -value $row.ows_SID
        $employee | Add-Member -type NoteProperty -name Account -value $row.ows_Account
        $employee | Add-Member -type NoteProperty -name FirstName -value $row.ows_FirstName
        $employee | Add-Member -type NoteProperty -name Department -value $row.ows_Department 
        $employee | Add-Member -type NoteProperty -name WorkPhone -value $row.ows_WorkPhone
        $employee | Add-Member -type NoteProperty -name FullLastName -value $row.ows_FullLastName 
        # we have records without accounts. use the ID as the unique.
        if($row.ows_SID) {
            $eHash.Add($row.ows_SID, $employee)
         } else {
            $eHash.Add($row.ows_ID, $employee)
         }


Then I call the AD module to get the AD people I need, and start looping through them. If I can find a SID in my hash, I might need to update, else I insert. I do this through a CAML structure. The replace statements to take care of any & should look like .Replace("&", "&")

get-aduser -filter * -Properties Enabled,ObjectClass,SamAccountName,GivenName,Surname,OfficePhone,Office,Department,DisplayName | 
Where-object -FilterScript {($_.Enabled -eq 'True')   -and ($_.Surname -ne $null) -and ($_.SamAccountName -match "^[^\.]*$")} |

foreach-object {

    # see if SID is in the hash table

        # you have to change SID to a string to match it to hash table key
        $sidstring = $_.SID.ToString()

          if(-not $eHash.ContainsKey($sidstring)) {
              write-host "new entry for " $_.SamAccountName  $_.SID
              $totalChanges += 1
             $i += 1
             $caml += "(Method ID='$i' Cmd='New')"
             $caml += "(Field Name='Title')" + $_.Surname.substring(0,1) + "(/Field)"
             $caml += "(Field Name='Account')" + $_.SamAccountName +  "(/Field)"
             $caml += "(Field Name='FirstName')" + $_.GivenName + "(/Field)"
          #   $caml += "(Field Name='Department')" + $_.Office + "(/Field)"
             $caml += "(Field Name='Department')" + $_.Department.Replace("&", "&") + "(/Field)"
             $caml += "(Field Name='WorkPhone')" + $_.OfficePhone + "(/Field)"
             $caml += "(Field Name='PhoneType')" + "Employee" + "(/Field)"
             $caml += "(Field Name='FullName')" + $_.GivenName + " " + $_.Surname.substring(0,1) + "(/Field)"
             $caml += "(Field Name='FullLastName')" + $_.Surname + "(/Field)"
             if($nickname -ne $_.GivenName) {
                  $caml += "(Field Name='Nickname')" + $nickname + "(/Field)"
             }
             $caml += "(Field Name='SID')" + $sidstring + "(/Field)"
             $caml += "(/Method)"


# done with loop through AD - write changes if any to SharePoint List


# if there are items to insert
if(($i -gt 0) -or ($u -gt 0) -or ($d -gt 0)) {

    $xmlDoc = new-object System.Xml.XmlDocument
    $batchelement = $xmlDoc.createElement("Batch")
    $batchelement.setattribute("OnError", "Continue")            
    $batchelement.setattribute("ListVersion", "1") 
    $batchelement.InnerXML = $caml 

    write-host $i Total Inserts
    write-host $u Total Updates
    write-host $d Total Deletions
  [System.Xml.XmlNode]$ndReturn = $service.UpdateListItems($listName, $batchelement)

} else {

    write-host "There are no additions or updates or deletions to Employee Phone List"
}

There's lots of other stuff in there as well, another section to get disabled users and delete them out of the list.

Like I said, probably other cool ways to do this, but I wanted to learn more Powershell and how to talk to AD so I did it this way.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a sharepoint.stackexchange
scroll top