1

I found a PowerShell script that supposed to use the User profile (User Information List) that is hidden and populated by Active Directory to populate a SharePoint list that you create using the Contacts app. I ran the script and received an error and I asked for help and Daniel Stölzner was able to find the bug that was causing the error. I then didn't know how to run it with the enumerator and he helped with that. I run it now and the list that I created in SharePoint called EmployeeDirectory is not getting updated with the user information.

I modified the script in this function (function Update-Contact($contact, $user, $domain, $webUrl)) because it appeared the names of the user information list weren't the same as the ones that were listed in the original script I also changed the names in the contact list (EmployeeDirectory) to match what I have in EmployeeDirectory. Below is the script. Does anyone know why I am not getting data in the SharePoint list?

I first issue this command to do the enumartion:
Enumerate-SPUserProfiles "https://dummy.dummysite.com" "EmployeeDirectory"

The script is called CreateEmployeeDirectory so after I do the above command I the issue this command: .\CreateEmployeeDirectoryEdited which executes the script.

Here is the script:

cls
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
    Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
function Enumerate-SPUserProfiles($webUrl, $listName)
{
    $x= [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
    $x= [System.Reflection.Assembly]::LoadWithPartialName("microsoft.sharepoint.portal")
    $x= [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server")
    $x= [System.Reflection.Assembly]::LoadWithPartialName("System.Web")
    $sites = Get-SPSite
    $context = [Microsoft.Office.Server.ServerContext]::GetContext($sites[0])
    $profileManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

    $web = Get-SPWeb $webUrl
    $list = $web.Lists[$listName]

    # gets all the user profiles, those that have domain\username as DisplayName are excluded
    $profileManager.GetEnumerator() | ?{$_.DisplayName -notlike '*\*' -and $_.ProfileType -eq "User" } | foreach-object { Update-PhoneBook $_ $web $list $webUrl } 
}

function Update-PhoneBook($user, $web, $list, $webUrl)
{
    if($user.Item("First name") -ne "" -and $user.Item("First name") -ne $null)
    {
        $spQuery = new-object Microsoft.SharePoint.SPQuery
        $userName = $user.Item("UserName")
        $camlQuery = "<Where><Eq><FieldRef Name='UserName' /><Value Type='Text'>$userName</Value></Eq></Where>";
        $spQuery.Query = $camlQuery
        $spQuery.RowLimit = 1
        $spListItemCollection = $list.GetItems($spQuery)
        $domain = (gwmi WIN32_ComputerSystem).Domain

        if($spListItemCollection.Count -ge 1)
        {
            Write-Host "Updating $username..."
            Update-Contact $spListItemCollection[0] $user $domain $webUrl
        }
        else
        {
            Write-Host "Adding $username..."
            $contact = $list.items.add();
            Update-Contact $contact $user $domain $webUrl
        }
    }
}

function Update-Contact($contact, $user, $domain, $webUrl)
{
    $lastName = $user.Item("Last name");
    $contact["Last Name"] = "$lastName";

    $firstName = $user.Item("First name");
    $contact["First Name"] = "$firstName";

    $workEmail = $user.Item("Work email");
    $contact["Email Address"] = "$workEmail";

    $workPhone = $user.Item("Work phone");
    $contact["Business Phone"] = "$workPhone";

    $department = $user.Item("Department");
    $contact["Department"] = "$department";

    $picture = $user.Item("Picture");
    $contact["Picture"] = "$picture";

    $userName = $user.Item("UserName");
    $contact["UserName"] = "$userName";

    $contact.update()
}
0

I believe you're referencing your $user properties incorrectly within Update-PhoneBook(). Instead of $user.Item("First name"), you'd want to do $user["FirstName"].

You can get a list of available properties for your user profiles by running the below code (assuming you already ran the above to generate $profileManager):

$user = $profileManager.GetUserProfile("username")
$user.Properties | select name, displayname| sort displayname

Then, just like my example above, you reference these via $user["fieldname"], where fieldname is the "Name" of the value you want.

That said, it's a bit curious if your script isn't returning any errors with that first if statement inside Update-PhoneBook(). If you make the above changes and still see no progress, I'd debug your foreach-object{Update-PhoneBook ...} statement to ensure your conditions aren't actually returning 0 values to loop through in the first place. You could easily start with the below to first check you're fetching user profiles in the first place:

$profileManager.GetEnumerator() | foreach{write-host $_.DisplayName}
  • I tried issuing this command $profileManager.GetEnumerator() | foreach{write-host $_.DisplayName} like you suggested but received an error. I ran it from the command prompt after I ran the script. This is the error: PS C:\Users\MikeZ> $profileManager.GetEnumerator() | foreach{write-host $_.DisplayName} You cannot call a method on a null-valued expression. At line:1 char:1 + $profileManager.GetEnumerator() | foreach{write-host $_.DisplayName} + + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull – MikeZ Sep 28 '16 at 13:31
  • I am not a powershell user so this is all new to me so I am not sure if I can just issue this command after I ran the script that I am having issue with to display the profiles. Should the profile information display on the screen when I issue that command? – MikeZ Sep 28 '16 at 13:33
  • Is this all saved in a script file that you're just running? If so, then none of your variables would be saved, as they'd close w/ the session once the script finished. Instead, open the script for editing with Windows Powershell ISE. If you don't have this, Google it, as it's server OS specific (should be fairly easy if you're on a server running SP2013). With this, you could run your script, then still issue commands such as the ones I suggested to see what values are returned (which yes, my last example would return the DisplayName for all user profiles). – Jordan Sep 28 '16 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.