Thursday, October 4, 2012

Windows mobile 6.5 - Using provisioning XML to set owner name

I'm currently working on converting a windows mobile application to run on an Intermec CN50 instead of the Motorola 65.  I've been working on the provisioning process using Intermec SmartSystems and a combination of their custom XML and provisioning XML.  We need the owner name to be the same on every device in order for some of the registered software to work properly.  I wanted to automate this using provisioning xml.  It proved more difficult than I expected as the owner information is stored in the registry in a binary field.  Below is the process to retrieve this and use the provisioning xml to set the binary value correctly. 

1)  Go onto a device and set the desired username. In this example we will use Joe Rep. 

2)  Connect the device to the computer through activesync and open the registry in your favorite mobile registry editor.  I personally prefer Soti PocketController Enterprise.  There is a 7 day trial, but the license is cheap and well worth it for all the features.

3)  Drill down to the HKCU\ControlPanel\Owner key.  You should see the following values:


4)  The Owner value is what we are interested in.  Note that the Name value is a string, but if we just set this value and then go into the control panel it gets overridden by the binary value.  We need to set both for the value to "stick".

5)  Export the Owner key to a .reg file and open in your favorite text editor. 

6)  Find the line that starts with:  "Owner"=hex:.  Copy all the values after hex:  and up to the next key.  Don't worry about removing any of the non hex chararcters or making it a single line.

7)  The provisioning XML requires a base64 encoded string.  We will use the Hex to base64 converter at http://tomeko.net/online_tools/hex_to_base64.php?lang=en.  I like this converter because it removes the extra characters the reg file added for you saving you time cleaning up the data.

8)  Paste the copied hex values into the first text box labeled Hex string and click the convert button.

9)  Select and copy the entire string in the text box labeled Output (base64).

10)  We are now ready to create our provisioning XML.  I always check MSDN to verify my data types.  http://msdn.microsoft.com/en-us/library/gg155033.aspx.

11)  The provisioning xml is below.  Just paste the string into the value and your provisioning XML is ready.

<wap-provisioningdoc>

<characteristic type="Registry">

  <characteristic type="HKCU\ControlPanel\Owner">

    <parm name="Name" value="Joe Rep" datatype="string" />
    <parm name="Owner"  value=""  datatype="binary" />

  </characteristic>

</characteristic>

</wap-provisioningdoc>

Monday, August 6, 2012

Sharepoint 2010 People Picker - The control is not available because you do not have the correct permissions

This message appears if the group assigned to the picker is set to allow only group members to view the group membership.

To fix:  Site Actions ->   Site Permissions ->  Select the group ->  Settings -> Group Settings

Change "Who can view the membership of the group?" to Everyone.


Tuesday, June 19, 2012

The specified web does not contain a reporting metadata list

I ran into this error while trying to debug a workflow in our production environment.  The solution was from Microsoft ( http://support.microsoft.com/kb/949605).  Just go onto the server, run the SharePoint 2010 Management Shell as admin and execute the following command:

stsadm -o activatefeature -name Reporting -url http://mysite.com/teams/TeamSite/ -force

Wednesday, April 4, 2012

Lotus Script to extract files

I am in the middle of replacing a large report routing system developed in Lotus Notes with a couple SharePoint sites and the Content Organizer feature.  Creating the new sites and routing the documents using the Content Organizer rules has proved easy.  I have to give big props to Microsoft on that feature.  The next big step came in extracting all the old documents and moving them to the SharePoint document libraries.  I took the code from (http://www.cubetoon.com/2007/accessing-the-local-file-sytem-from-lotusscript/) and customized it to do what I needed.  My script is below in case anyone is running into a similar requirement.



Sub Initialize
   
    Dim s As NotesSession
    Dim db As NotesDatabase
    Dim view As NotesView
    Dim Doc As NotesDocument
    Dim rtitem As Variant
    Dim CreatedDate As Variant
    Dim i As Integer
    Dim FileName As String
    Dim FileExtension As String
    Dim testString As String
    Dim SavedFileName As String
   
   
   
    Dim ExtractFolder As String
    ExtractFolder = "C:\ReportRouterFiles\"
   
    Set s = New NotesSession
    Set db = s.CurrentDatabase
    Set view = db.GetView ("By Report ID")
    Set doc = view.GetFirstDocument
   
    Set rtitem = doc.GetFirstItem ("Body")
   
    While Not ( doc Is Nothing )
        Set rtitem = doc.GetFirstItem ("Body")
       
        If (rtitem.type = RICHTEXT) Then
            Forall o In rtitem.EmbeddedObjects
                CreatedDate = Format(doc.Created, "yyyymmdd")
               
                FileName = o.Name
               
                testString = Mid(FileName, Len(FileName) - 3, 1)
               
                If (testString = ".") Then
                    FileExtension = Mid(FileName, Len(FileName) - 3, 4)
                    FileName = Mid(FileName, 1, Len(FileName) - 4)
                   
                Else ' I'm going to assume the file extension is 4
                    FileExtension = Mid(FileName, Len(FileName) - 3, 5)
                    FileName = Mid(FileName, 1, Len(FileName) - 5)
                   
                End If
               
                SavedFileName = FileName & "_" & CreatedDate & FileExtension
               
               
                If Dir$(ExtractFolder & SavedFileName, 0 ) = "" Then
                    'there is no file for that day, go ahead and extract
                Else
                    'the file exists, so append a unique number to it before extracting
                    i = 1
                    While i < 10
                        SavedFileName = FileName & "_" & CreatedDate & "_" & i & FileExtension
                       
                        If Dir$(ExtractFolder & SavedFileName, 0 ) = "" Then
                            i = 11
                        End If
                       
                        i = i + 1
                    Wend
                End If
               
            'could put check here in case we have a _9 file and warn me, but should not have more than 1 so I'm not worried about it
                o.extractFile(ExtractFolder & SavedFileName)
            End Forall
        End If
       
        Set doc = view.GetNextDocument( doc )
    Wend
   
End Sub

Monday, March 26, 2012

SQL Server table size

Our BI environment is growing at a rapid rate.  I was looking for a script to give me the size of all the tables.  I found a good one here ( http://devio.wordpress.com/2007/10/11/how-much-space-do-my-sql-server-tables-use/).  A copy of the script is posted below.



create table #t
(
  name nvarchar(128),
  rows varchar(50),
  reserved varchar(50),
  data varchar(50),
  index_size varchar(50),
  unused varchar(50)
)

declare @id nvarchar(128)
declare c cursor for
select name from sysobjects where xtype='U'

open c
fetch c into @id

while @@fetch_status = 0 begin

  insert into #t
  exec sp_spaceused @id

  fetch c into @id
end

close c
deallocate c

select * from #t
order by convert(int, substring(data, 1, len(data)-3)) desc

drop table #t

Friday, March 16, 2012

This page is based on a file from the site's definition, and you do not have permission to customize it.

A developer was receiving the error "This page is based on a file from the site's definition, and you do not have permission to customize it. Contact your site collection administrator."  This was on our development site where all of IT was an owner of the site.  The problem was in the site collection administration settings ->  SharePoint Designer Settings.  Made sure all the boxes were checked and the error went away.

Thursday, February 9, 2012

Sharepoint 2010: Department calendar - Hide time and show more event text

In the calendar, I wanted to hide the start and end times while wrapping the title to allow two lines of text.  A quick Google didn't lead to any answers, so off it was to firebug figuring I could get it done with a little CSS.  Sure enough it was pretty easy and the solution I'm using is below.

1)  Edit the calendar view in advanced mode with SPD.
2) Find the style section near the very bottom of the page and replace it with:

<style type="text/css">
.ms-bodyareaframe {
    padding: 0px;
  }
.ms-acal-title {white-space:normal;}
.ms-acal-time{display:none;}
.ms-acal-rootdiv div{white-space:normal;}
</style>


Wednesday, February 8, 2012

Sharepoint 2010: Workflow is not updating

I have been working on a department calendar for time off requests.  The list has a couple workflows to send emails to the approvers and the person who submitted the request.  I was updating the workflow in SharePoint designer, saving, and publishing.  I changed one of the workflows to "Start automatically when an item is changed".  I was still not receiving the test emails when the item was changed.  I then noticed when looking at the list in SPD the workflow still showed as manual start.  I tried everything I could think of, but couldn't get the list to reflect the changes after I saved and published the workflow.  I ended up recreating the workflow from scratch and everything worked.  It was annoying but at least it was fixed.....then suddenly a second workflow stopped sending the updates to the server.  I would change the email, but would still get the old version.  I dug around for a little bit and finally found this fix. 

It is taken from:  http://blogs.msdn.com/b/sharepointdesigner/archive/2007/03/27/tip-clearing-the-spd-workflow-assembly-cache.aspx



If you are building a workflow activity on WSS for SPD you may have to update your activity DLL regularly (say to fix bugs or alter behaviors).  Sometimes when you do this, SPD won't recognize your changes to the activity and instead appear to be using the 'old' DLL.  Depending on what you've changed in the activity on the server, SPD may not allow you to use this activity at all.  This is due to a mismatch between the server's activity and the SPD client's cached activity.  To fix this problem its a good idea to clear your SPD activity cache whenever you update your activities DLL on the server.
To clear the SPD activity cache:
1. Close SPD.
2. Open “My Computer”.
3. Go to %System Drive%\Documents and Settings\%user%\Local Settings\Application Data\Microsoft\WebSiteCache (If you are running Vista, that path is different - look for %System Drive%\Users\%user%\AppData\Local\Microsoft\WebSiteCache).
4. Go to a directory that looks similar to the name of the website you were connecting to. (Alternatively, you can just delete all these directories and everything should work when you boot SPD).
5. Delete the assembly with the name similar to the one you are changing.
6. Boot SPD.
7. You can now work with your updated activity.

Thursday, February 2, 2012

Sharepoint: : An unsecured or incorrectly secured fault was received from the other party

This was another fun one I ran into today.  The site is a reporting center with both Performance Point and Reporting Services reports.  The error started after we moved the site from our development environment to our test environment.  

The error reported in the SharePoint logs was:


An unexpected error occurred.  Error 17265.  Exception details: System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when verifying security for the message. 


The problem ended up being that after we rebooted the test web server, the clock was 15 minutes ahead.  Resetting the clock fixed this error(yes, changing the time fixed the security exception.....).   Just another fun day in the world of SharePoint 2010.

Tuesday, January 31, 2012

Powershell scripts to delete and add users and groups to Sharepoint 2010 site collections

I've put together the following scripts to first clear out all users from a Sharepoint site collection.  The scripts iterate through each group clearing out all of the users, as well as users not in a group.  The scripts then add users to each group.  All groups are passed in regardless of whether or not the group exists for the site collection.  If the group does not exist you will get a yellow warning message.  I've tried to make the scripts as straight forward to use as possible.  The scripts were created due to issues with Axceler ControlPoint not doing exactly what I would like to.  Look for a post soon for my full review of ControlPoint.

An example using the scripts below:

$url = "http://mysharepointsite.com/"
#Sitename is the preface for the groups
$sitename = "MySiteName"

# if no domain is specified, it defaults to DefaultDomain(change this for your environment)
#to add a user, add a comma and their name in quotes to the correct group
#AD groups can be added as well
$portalowners =  "user1", "user2"
$portalmembers = ""
$portalvisitors = "user3", "user4"
$portaldesigners = ""
$portalapprovers = "AD Group1", "AD Group2"

#include the addusers.ps1 file
$path = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
. (Join-Path -Path $path -ChildPath AddUsers.ps1)

Add-PSSnapin Microsoft.SharePoint.Powershell -erroraction silentlycontinue

#first clear out all users
ClearUsers $url

#set the group names
$OwnersGroup = $sitename + " Owners"
$MembersGroup = $sitename + " Members"
$VisitorsGroup = $sitename + " Visitors"
$DesignersGroup = "Designers"
$ApproversGroup = "Approvers"

#add the users
AddUsersToGroup $url  $OwnersGroup  $portalowners
AddUsersToGroup $url $MembersGroup  $portalmembers
AddUsersToGroup $url $VisitorsGroup $portalvisitors
AddUsersToGroup $url  $DesignersGroup $portaldesigners
AddUsersToGroup $url  $ApproversGroup $portalapprovers




The script with the functions to add and clear users:

File:  AddUsers.ps1

Function AddUsersToGroup ($url, $groupname, $userarray)
{
    # Get SPSite object
    $site = get-spsite $url -ErrorAction silentlycontinue

    if($site) {
        #check to see if the group exists on the site
        #added this because I want to use the same groups regardless of site template
        #for example the approvers group will always get passed in, but won't exist on a team site
        $groups = $site.RootWeb.SiteGroups
       
        $groupexists = $false
       
        foreach($group in $groups)
        {
            if( $group.Name.tolower() -eq $groupname.tolower())
            {
                $groupexists = $true
                break
            }
       
        }
       
        if($groupexists)
        {
            # Get SPGroup
            $group = $site.RootWeb.SiteGroups[$groupname]

            if($group) {
                # Loop through and add users
                foreach($user in  $userarray)
                {   
                    # Get user fields
                    $username = $user.trim()
                   
                    if($username.Length -gt 0)
                    {
                        #check if username contains a domain, if not add the default domain
                        #Edit the default domain to your domain
                        if($username.Contains("\"))
                        {
                        }else
                        {
                            $username = "DefaultDomain\" + $username
                        }
                       
                        Write-Host "Add user '$username' to group '$groupname' to site '$url'..."

                        # Add user to group
                        $group.AddUser($username , "", "", "")

                        Write-Host "User added" -ForeGroundColor Green
                       
                   
                    }
                   
               
                }
            }else
            {
                Write-Host "Can't open group '$groupname'" -ForeGroundColor Red
            }
        }else
            {
                Write-Host "Group '$groupname' does not exist on this site" -ForeGroundColor Yellow
            }
    } else
    {
        Write-Host "Can't open site '$url'" -ForeGroundColor Red
    }

    $site.dispose()
}


Function ClearUsers ($url)
{

    # Get SPSite object
    $site = get-spsite $url -ErrorAction silentlycontinue
   
    if($site) {
   
        #first remove users not in a group
        $removeUsers =  $site.RootWeb.Users
       
        #create an array to hold the users
        $UsersToDelete = @()
       
        #first build our list
         foreach ($removeUser in $removeUsers)
        {
            #don't remove the system account
            $test = $removeUser.LoginName.ToLower().Contains("system")
           
            if($test -eq $false)
            {
                $UsersToDelete += $removeUser.UserLogin
            }
        }
       
        $removeUsers = $UsersToDelete
       
        #now delete the users
        foreach ($removeUser in $removeUsers)
        {
                Write-Host "Removing individual user '$removeUser' from site '$url'..."
           
                $site.RootWeb.Users.Remove($removeUser)
        }
           
   
        # Get SPGroup
        $groups = $site.RootWeb.SiteGroups

        #now clear all users from groups
        foreach ($group in $groups)
        {
            $removeUsers = $group.Users
           
            $groupname = $group.Name
           
            foreach ($removeUser in $removeUsers)
            {
                    Write-Host "Removing user '$removeUser' from group '$groupname' from site '$url'..."
                    $group.RemoveUser($removeUser)
            }
           
        }

    }else
        {
              Write-Host "Can't open site '$url'" -ForeGroundColor Red
        }

       
    $site.dispose()

}