tirsdag den 3. januar 2012

App-V, Office 2010 and Ribbons

Updated 4th Jan 2012: And that didn’t work once rolled out in production anyway. Back to the drawing board. :-(

I explained how to use SuperOffice inside Microsoft Application Virtualization client in a former blog post. What I didn’t mention was that since we did that, we had a annoying problem with that. Every time a user started Microsoft Word, they would get a popup saying “An error occurred and this feature is no longer functioning properly. Please run Setup and select “Repair…” to restore this application

image

I opened a Support Case at Microsoft and we have been troubleshooting this issue for several months and today we finally cracked it. Doing installation of SuperOffice they register an Office Add on and register some Office Ribbons. They have “messed” up the registry keys a bit thou. Some things are registered for Office 12 (office 2007) and some tings get’s registered for Office 14 ( Office 2010 )

doing sequencing, after installing SuperOffice,
export hklm\software\Wow6432Node\Microsoft\Office\12.0  and delete it.
replace \12.0\ with \14.0\ in the reg file, and import it.

Now word will function again.

onsdag den 21. december 2011

ID3206: A SignInResponse message may only redirect within the current web application:

I got a question in a remark on ADFS 2.0 and ASP.NET and wanted to do a post about it instead of trying to fit in code inside a remark too.

Sometimes you might see the above error. And I can understand why it can be frustrating at times, so ill try and clarify what it means.

You create a sign message and redirect the user to the ADFS/STS. The user logs in successfully and gets send back with a token, and now WIF on the webserver say’s “go away, you are trying to login with a token issued for another domain/application than me.

The key here is your return URL. When you add a Relying Party on your ADFS server, you specify a WS-Federation Passive Endpoint. Your return URL need to be within same scope as your WS-Federation Endpoint URI.

image
I have added the code I’m using now, and added a few comments. Should clear things up a bit.

Code Snippet
  1. ' basicly this tell adfs, to redirect the user onward to some other STS. For most people this should not be specified.
  2. Dim HomeRealm As String = "urn:admin.wingu.dk"
  3.  
  4. 'What Identity did we specify in the "Relying Party Trusts" on the ADFS server
  5. 'This has to also be listed in web.config under <microsoft.identityModel><service><audienceUris>
  6. ' or you will get ID1038: The AudienceRestrictionCondition was not valid because the specified Audience is not present in AudienceUris.
  7. ' This will most often be an URI, like https://admin.wingu.dk/SSI2 , but could also be an URN, like "urn:admin.website.ssi2"
  8. Dim Realm As String = ("https://admin.wingu.dk" & Request.ApplicationPath & "/").ToLower
  9.  
  10. ' Lets inspect and modify the Return URL
  11. ' If this falls out of scope from what you specefied under WS-Federation Passive Endpoint, when adding you
  12. ' Relying Party on the ADFS server, you will get
  13. ' ID3206: A SignInResponse message may only redirect within the current web application:
  14. '
  15. ' Basicly, if you want several endpoints for you website. Like www.1.com and www.2.com or
  16. ' www.1.com/app1 and www.1.com/app1, add more Relying Party's, one for each.
  17. ' There is another way, maybe ill do a blog about that someday
  18.  
  19. Dim ReturnURI As New UriBuilder(ReturnUrl.ToLower)
  20. ' We need to use HTTPS, no matter what, so
  21. ReturnURI.Scheme = "https"
  22. ReturnURI.Port = 443
  23. 'I dont want to redirect back to my self. This can be ok in some sceenarios
  24. If ReturnURI.Path.Contains("login.aspx") Then ReturnURI.Path = Request.ApplicationPath & "/"
  25. ' change localhost / computernamer or what ever, to the fqdn used on the ADFS to redirect back to
  26. ReturnURI.Host = "admin.wingu.dk"
  27. ReturnUrl = ReturnURI.ToString
  28.  
  29. Dim authModule As WSFederationAuthenticationModule = FederatedAuthentication.WSFederationAuthenticationModule
  30. authModule.PassiveRedirectEnabled = True
  31. Dim mess As WSFederation.SignInRequestMessage = authModule.CreateSignInRequest("passive", ReturnUrl, False)
  32.  
  33. mess.HomeRealm = HomeRealm
  34. mess.Realm = Realm
  35. Dim redirURL As String = mess.WriteQueryString()
  36. Response.Redirect(redirURL)

onsdag den 14. december 2011

SQL user does not use default schema

So I was troubleshooting an installation of SuperOffice Customer Service. When running the installer it would fail with an ODBC driver error saying something down the line of “’config’ object not found” and you could see it was doing a “select count(*) from config”

I jumped over to the SQL server and saw that the SuperOffice SQL user did not have crm7 schema set as default schema and was not owner. So I chanced that, and tried again. I would still failed. So I open a new query in Management studio and did a “select * from config” .. that should work, but didn’t, I would still get no such object.

after goggling a while I decided to do a alter user, so opened the “help” page for “alter user” and voila, after reading the page I suddenly knew what was wrong.

The value of DEFAULT_SCHEMA is ignored if the user is a member of the sysadmin fixed server role. All members of the sysadmin fixed server role have a default schema of dbo.

The person who had installed superoffice had added the SQL user crm7 to the sysadmin role, and as you can see, that will break the schema role assignment. After removing the user from sysadmin, everything worked again.

søndag den 23. oktober 2011

Deploy CRM List Component though PowerShell

as always I did a few searches on Google. Most hits just explained how to upload the WSP file and then call the AllowHtcExtn.ps1 script.

On blog did explain you could use Add-SPSolution and Install-SPSolution but that didn’t work for me.

$solution = Get-SPSolution crmlistcomponent.wsp
if(!$solution){ $solution = Add-SPSolution X:\SPS_2010_prov\listekomponent\en\crmlistcomponent.wsp }
Install
-SPSolution -WebApplication "https://$webappurl" $solution -GACDeployment -Force

The solution didn’t show up in Solution Gallery inside SharePoint. And when I tested from CRM 2011 it kept complaining the List Component isn't installed.


I have just been to Microsoft Campus Days in Copenhagen ( kind of a “mini TechEd” ) and one of the session I was attending was about SharePoint Online and how Microsoft only allow Sandbox solutions, and then it hit me. Maybe the CRM list Component is a sandbox solution and needs to be deployed that way. We have a winner!


So we end up with


Write-Host "Starting Sharepoint User Code Service"
stsadm
-o provisionservice -action start -servicetype Microsoft.SharePoint.Administration.SPUserCodeService -servicename SPUserCodeV4

Write
-Host "Install crmlistcomponent if needed"
$solution = Get-SPUserSolution crmlistcomponent.wsp -Site "https://$webappurl" -ea 0
if(!$solution){
$temp = Add-SPUserSolution X:\SPS_2010_prov\listekomponent\en\crmlistcomponent.wsp
$solution = Get-SPUserSolution crmlistcomponent.wsp -Site "https://$webappurl"
}

Write
-Host "Active crmlistcomponent if needed"
if($solution.Status -ne 'Activated'){
$solution = Install-SPUserSolution $solution -Site "https://$webappurl"
}

Write
-Host "Make sure .htc file name extension is an allowed file type"
$app = Get-SPWebApplication -Identity "https://$webappurl"
$app.AllowedInlineDownloadedMimeTypes.Add("text/x-component")
if(!$app.WebFileExtensions.Contains("htc")){
Write
-Host "Adding .htc file name extension to the list of allowed file types."
$app.WebFileExtensions.Add("htc")
$app.Update()
}

lørdag den 22. oktober 2011

Find owner of Fulltext catalog

Once in a while I would get this error when dropping SQL logins

The database principal owns a fulltext catalog in the database, and cannot be dropped.

Changing the owner is easy enough, but I’m doing this by scripts and needed a way to find the owner of the fulltext catalog. Took a while but finally managed to get the result with

select cat.fulltext_catalog_id, cat.name 
from sys.fulltext_catalogs as cat
inner join sys.database_principals as dp2
on cat.principal_id = dp2.principal_id


Perfect, so lets script that, and we get something like


$SQLLogin = 'soadmin_SOTEST2'
$sqlserver = 'sql01.int.wingu.dk'
$database = 'SO7_SO7SOTEST2'

$sql = "select cat.fulltext_catalog_id, cat.name from sys.fulltext_catalogs as cat "
$sql = ($sql + " inner join sys.database_principals as dp2 on cat.principal_id = dp2.principal_id ")
$sql = ($sql + "where dp2.name = '$SQLLogin'")

$rs = Invoke-Sqlcmd -ServerInstance $sqlserver -Database $database -Query $sql
foreach($row in $rs){
$sql = ("ALTER AUTHORIZATION ON Fulltext Catalog::[" + $row.Name + "] TO dbo")
Invoke
-Sqlcmd -ServerInstance $sqlserver -Database $database -Query $sql
}

mandag den 10. oktober 2011

Working with SuperOffice though PowerShell

This powershell snap in is not meant to be a complete SuperOffice client, but for most basic stuff you can use this. Like say, you want to run a batch job everyday to update/sync information's from anther system and SuperOffice

working with powershell makes a lot of things a lot easier. Lets have a look at a few examples

First lets connect to SuperOffice. If you have the superoffice.config from your client laying around somewhere you can easily connect using that.

$module = Get-Module | where {$_.name -eq 'wingu.SuperOffice.SnapIn'}
if($module -eq $null){
$module = Get-Module -ListAvailable | where {$_.name -eq 'wingu.SuperOffice.SnapIn'}
if($module){ import-module wingu.SuperOffice.SnapIn }
}

$config = Get-SO7config c:\superoffice.config | Set-SO7config
$config.Username = $config.Explicit.DBUser
$config.Password = $config.Explicit.DBPassword

So, just to validate everything is working, lets get the license information
$LicenseInfo = Get-SO7LicenseInfo
# To replace running license use
#
Set-SO7LicenseInfo -CompanyName 'Happy Ducks Holding ApS' -SerialNumber '1234'
#
To Update current license. ( like if you buy more user licenses )
#
Set-SO7LicenseInfo $LicenseInfo

To see what credentials is associated with alz@sotest1.local and if he is logged on right now, you could so something like this


Get-SO7Person -email alz@sotest1.local | Get-SO7Credentials

Or to have a loot at who is using SuperOffice right now
Get-SO7Credentials | where {$_.CredentialType -eq 'Ticket' }

( this will not be accurate, since cleanup of ticket’s is only done when a user logs in. but still … )

Do you want a list of Persons asscociated with Contact ‘hestehøj a/s’ ?


Get-SO7Contact 'Hestejøj AS' | Get-SO7Person

Want to create a new Associate, with AD login ?


$logonName = 'alz'
$upn = 'alz@sotest1.local'
$FirstName = 'Allan'
$Lastname = 'Zimmermann'

# Get Associate if exists
$CRM7User = Get-SO7Associate -logonName $logonName -ea 0
# Get Person with email corrosonding to upn, if exists
$CRM7Person = Get-SO7Person -email $upn -ea 0
if((!$CRM7User) -and (!$CRM7Person)){
# could not find a person nor Associate so create both
$CRM7User = New-SO7Associate -FirstName $FirstName -Lastname $Lastname -logonName $logonName -Email $upn -AdUser
$CRM7User = Get-SO7Associate -logonName $logonName -ea 0
$CRM7Person = Get-SO7Person -email $upn -ea 0
}
if((!$CRM7User) -and ($CRM7Person)){
# Person exists, but have no Associate so create it and link to person
$CRM7User = New-SO7Associate -person $CRM7Person -logonName $logonName -Email $upn -AdUser
$CRM7User = Get-SO7Associate -logonName $logonName -ea 0
}
# Assign a UserLicense, allow login, and enable Windows/web
$CRM7User | Enable-SO7Associate

Or, create with a CRM5 password (not ad login) ?
$logonName = 'alz'
$upn = 'alz@sotest1.local'
$FirstName = 'Allan'
$Lastname = 'Zimmermann'
$Password = 'Passw0rd'

# Get Associate if exists
$CRM7User = Get-SO7Associate -logonName $logonName -ea 0
# Get Person with email corrosonding to upn, if exists
$CRM7Person = Get-SO7Person -email $upn -ea 0
if((!$CRM7User) -and (!$CRM7Person)){
# could not find a person nor Associate so create both
$CRM7User = New-SO7Associate -FirstName $FirstName -Lastname $Lastname -logonName $logonName -Email $upn -Password $Password
$CRM7User = Get-SO7Associate -logonName $logonName -ea 0
$CRM7Person = Get-SO7Person -email $upn -ea 0
}
if((!$CRM7User) -and ($CRM7Person)){
# Person exists, but have no Associate so create it and link to person
$CRM7User = New-SO7Associate -person $CRM7Person -logonName $logonName -Email $upn -Password $Password
$CRM7User = Get-SO7Associate -logonName $logonName -ea 0
}
# Assign a UserLicense, allow login, and enable Windows/web
$CRM7User | Enable-SO7Associate

anyway, here is a complete list of commands.
Get-Command -Module wingu.SuperOffice.SnapIn


Close-SO7Session
Decrypt-SO7H
Disable-SO7Associate
Enable-SO7Associate
Encrypt-SO7H
Get-MySO7Identity
Get-SO7Associate
Get-SO7Business
Get-SO7config
Get-SO7Contact
Get-SO7Country
Get-SO7Credentials
Get-SO7Email
Get-SO7LicenseInfo
Get-SO7Person
Get-SO7Secret
Get-SO7SystemInfo
New-SmartProcess
New-SO7Associate
New-SO7Business
New-SO7Contact
New-SO7Credentials
New-SO7Person
Remove-SO7Associate
Remove-SO7Business
Remove-SO7config
Remove-SO7Contact
Remove-SO7Credentials
Remove-SO7Email
Remove-SO7Person
Save-SO7config
Set-SO7config
Set-SO7LicenseInfo
Set-SO7Person


lørdag den 8. oktober 2011

SharePoint and WebDAV–part 2

So I was troubleshooting mapping SharePoint though WebDAV and found I had to open the SharePoint site though office in one way or the other, in order to successfully map it. That was true, but for one very specific reason.

Talking about cookies, you need to know there is 2 kinds of cookies. Session Cookies and Persistent cookies. Session cookies only “lives” as long as your browser is open. As soon as you close *ALL* your browser windows they cookie will expire. Persistent cookies will stay on your machine until the expire date on the cookie is hit.

When you setup SharePoint to use Claimsbased authentication SharePoint save a cookie on your machine called the “FedAuth” cookie. This is your what authenticate you every time you hit SharePoint. It gets set when the Identity Provider (STS/ADFS) makes your browser “post” your claims to https://fqdn/_trust/ .It gets removed when you click “sign out” or “Sign in as Different User”.

The WebDAV client, and various Office applications does support working with websites that facilitate Claimsbased authentication, but they cannot authenticate you. It assumes you have a FedAuth cookie on your machine. Some times you will get a browser popup, but there are places this wont happen (like with WebDAV). I had told SharePoint to use Session Cookies, since that would make more sense when working with SharePoint. You login you do your stuff, you might sign out, or you might close your browser. Next time you hit it, it asks you to login. I was happy, everyone else was happy. That is, until someone needed to work with SharePoint from within Outlook and though WebDAV.

SharePoint will standardly run with Persistent Cookies, but you can change this though PowerShell. Set UseSessionCookies to $true or $false. If you need to work with SharePoint though Office or WebDAV you need to set this to $false (default)

$snapin = Get-PSSnapin | where {$_.name -eq 'Microsoft.SharePoint.PowerShell'}
if($snapin -eq $null){ Add-PSSnapin Microsoft.SharePoint.PowerShell }

$sts = Get-SPSecurityTokenServiceConfig
$sts.UseSessionCookies = $false
$sts.Update()
iisreset

As far as I know, you cannot set this per site.


Next you want to make sure Office/Web Client can read the cookie. Referee to “Persistent cookies are not shared between Internet Explorer and Office applications