Installation on non-english systems (French)

Jul 19, 2011 at 4:52 PM

I'm using this script to install SharePoint in French. All is in french : the OS, the Active Directory, the SharePoint ISO. I didn't need to add a language pack since it's already includes in my ISO.

But on few points, the script stop on unmanaged language terms. I made some modification, may be you could put them in a future version.

First, the local Administrators group. His name change with the OS lang (in french, it's Administrateurs). Instead, i call to the system to get the the true name of the Administrators group (which always have the SID S-1-5-32-544)

 - On the ConfigureFarmAdmin function

Function ConfigureFarmAdmin([xml]$xmlinput)
{   
	# Edit *Language Hack*
	if(!$builtinAdminGroup)
	{
		$builtinAdminGroup = (Get-WmiObject -Class Win32_Group -computername $env:COMPUTERNAME -Filter "SID='S-1-5-32-544' AND LocalAccount='True'" -errorAction "Stop").Name
	}
	# + Replace string "Administrators" in lines [ADSI]"WinNT... by "$builtinAdminGroup" (3 occurences)
	If (($xmlinput.Configuration.Farm.Account.getAttribute("AddToLocalAdminsDuringSetup") -eq $true) -and (ShouldIProvision($xmlinput.Configuration.ServiceApps.UserProfileServiceApp) -eq $true))
    {
        WriteLine
		#Add to Admins Group
        $FarmAcct = $xmlinput.Configuration.Farm.Account.Username
        Write-Host -ForegroundColor White " - Adding $FarmAcct to local Administrators (only for install)..."
        $FarmAcctDomain,$FarmAcctUser = $FarmAcct -Split "\\"
        Try
    	{
    		([ADSI]"WinNT://$env:COMPUTERNAME/$builtinAdminGroup,group").Add("WinNT://$FarmAcctDomain/$FarmAcctUser")
            
[...]

 - On theAddManagedAccounts function

Function AddManagedAccounts([xml]$xmlinput)
{
    [...]
		# Get the members of the local Administrators group
		# Edit *Language Hack*
		if(!$builtinAdminGroup)
		{
			$builtinAdminGroup = (Get-WmiObject -Class Win32_Group -computername $env:COMPUTERNAME -Filter "SID='S-1-5-32-544' AND LocalAccount='True'" -errorAction "Stop").Name
		}
		$AdminGroup = ([ADSI]"WinNT://$env:COMPUTERNAME/$builtinAdminGroup,group")
		# This syntax comes from Ying Li (http://myitforum.com/cs2/blogs/yli628/archive/2007/08/30/powershell-script-to-add-remove-a-domain-user-to-the-local-administrators-group-on-a-remote-machine.aspx)
		[...]
			# Add managed account to local admins (very) temporarily so it can log in and create its profile
	    		If (!($LocalAdmins -contains $ManagedAccountUser))
				{
					([ADSI]"WinNT://$env:COMPUTERNAME/$builtinAdminGroup,group").Add("WinNT://$ManagedAccountDomain/$ManagedAccountUser")
				}
		[...]
				# Remove managed account from local admins unless it was already there
	    		If (-not $AlreadyAdmin) {([ADSI]"WinNT://$env:COMPUTERNAME/$builtinAdminGroup,group").Remove("WinNT://$ManagedAccountDomain/$ManagedAccountUser")}

 

There is another discussion about errors in rights (here : http://autospinstaller.codeplex.com/discussions/262342). For now, i bypass this problem like with this code. It's not perfect, but it works.

- On the CreateMetadataServiceApp funtion :

 

$AccountPrincipal = New-SPClaimsPrincipal -Identity $account.username -IdentityType WindowsSamAccountName			
# Give permissions to the claims principal you just created
# Edit *Lang Hack*
if(!$AdminLCID)
{
	$AdminCulture = $(Get-SPWeb "Http://$($env:COMPUTERNAME):$AdminPort").UICulture
	$AdminLCID = $AdminCulture.LCID
	Write-Host " - Central Admin Lang : "+$AdminCulture.DisplayName+" ($AdminLCID)"
}
switch($AdminLCID)
{
	#1036: fr-FR
	1036 
	{
		Grant-SPObjectSecurity $MetadataServiceAppSecurity -Principal $AccountPrincipal -Rights "Magasin de termes avec accès total"
	}
	default
	{
		Grant-SPObjectSecurity $MetadataServiceAppSecurity -Principal $AccountPrincipal -Rights "Full Access to Term Store"
	}
}

- On the CreateUserProfileServiceApplication function

# Create variables that contains the claims principals for MySite App Pool, Portal App Pool and Content Access accounts
$MySiteAppPoolAcctPrincipal = New-SPClaimsPrincipal -Identity $MySiteAppPoolAcct -IdentityType WindowsSamAccountName
$PortalAppPoolAcctPrincipal = New-SPClaimsPrincipal -Identity $PortalAppPoolAcct -IdentityType WindowsSamAccountName
$ContentAccessAcctPrincipal = New-SPClaimsPrincipal -Identity $ContentAccessAcct -IdentityType WindowsSamAccountName
# Edition *Lang Hack*
if(!$AdminLCID)
{
	$AdminCulture = $(Get-SPWeb "Http://$($env:COMPUTERNAME):$AdminPort").UICulture
	$AdminLCID = $AdminCulture.LCID
	Write-Host "Central Admin Lang : "+$AdminCulture.DisplayName+" ($AdminLCID)"
}
switch($AdminLCID)
{
	#1036: fr-FR
	1036 
	{
		# Give 'Full Control' permissions to the MySite App Pool and Portal App Pool account claims principals
		Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $MySiteAppPoolAcctPrincipal -Rights "Contrôle total"
		Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $PortalAppPoolAcctPrincipal -Rights "Contrôle total"
		# Give 'Retrieve People Data for Search Crawlers' permissions to the Content Access claims principal
		Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $ContentAccessAcctPrincipal -Rights "Extrait les données de personnes pour les robots de recherche"
	}
	default 
	{
		# Give 'Full Control' permissions to the MySite App Pool and Portal App Pool account claims principals
		Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $MySiteAppPoolAcctPrincipal -Rights "Full Control"
		Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $PortalAppPoolAcctPrincipal -Rights "Full Control"
		# Give 'Retrieve People Data for Search Crawlers' permissions to the Content Access claims principal
		Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $ContentAccessAcctPrincipal -Rights "Retrieve People Data for Search Crawlers"
	}
}

- On the CreateEnterpriseSearchServiceApp function, you use a hard coded name. Why don't use a type like in many other places in the script :

# Edition *Lang Hack*
# Adaptation multi-langues
#Start-SPServiceInstance (Get-SPServiceInstance | where { $_.TypeName -eq "Search Query and Site Settings Service"}).Id | Out-Null
Start-SPServiceInstance (Get-SPServiceInstance | where { $_.GetType().ToString() -eq "Microsoft.Office.Server.Search.Administration.SearchQueryAndSiteSettingsServiceInstance"}) | Out-Null

- On the Run-HealthAnalyzerJobs function, you search match on DisplayName. It's better to use Name, which is the same in all langs.

Function Run-HealthAnalyzerJobs
{
	# Edition *Lang Hack*
	#$HealthJobs = Get-SPTimerJob | Where {$_.DisplayName -match "Health Analysis Job"}
	$HealthJobs = Get-SPTimerJob | Where {$_.Name -match "health-analysis-job"}
	# /Edition
	Write-Host -ForegroundColor White " - Running all Health Analyzer jobs..."
	ForEach ($Job in $HealthJobs)
	{
		$Job.RunNow()
	}
}

With these few changes, the installation process have suceeded.

For other languages, on the "rights" problems, you can juste edit the switch block and add yours. I even think about an array of translations, but useless in my case.

Jul 19, 2011 at 5:09 PM
Edited Jul 19, 2011 at 5:32 PM

Thank you, i used to have the same issue ...

Don't you have any problem with the superaccount configuration when creating a webApplication (:80 & :8080) ? 

Jul 20, 2011 at 8:52 AM

By superaccount, you mean the cache accounts ?

No, the only time i stop on that point was when i forgot to specify an account (i was thinking it's optionnal in a SharePoint farm, but in the script, it's compulsory).

Jul 20, 2011 at 9:30 AM

Yes... But it's fine now ! Sorry about that.

Jul 21, 2011 at 9:24 AM

Well done. I had the same issue on german servers...

Jul 21, 2011 at 11:07 AM

Thanks, your workaround on the CreateMetadataServiceApp function looks far better than mine. ;)

Aug 1, 2011 at 11:12 AM

I discover another "bugged" point on non-english installation, on the attribution of the cache accounts.

The original script use a DiplayName to set the rights of the accounts cache, which don't works on foreign langages. It put the account without prompting errors, but the site can't be accessed by any accounts ! When we check via the central admin, there is the accounts, but no rights assigned to them !

Here is my workaround :

On the Set-WebAppUserPolicy function :

I change the "where" parameter to put the internal name (the Type value) instead of the display name (Name value) :

 

Function Set-WebAppUserPolicy($wa, $userName, $displayName, $perm) 
{
[...]
[Microsoft.SharePoint.Administration.SPPolicyRole]$policyRole = $wa.PolicyRoles | where {$_.Type -eq $perm}
[...]
}

On the ConfigureObjectCache function :

I change the key words to use the internal name : juste remove the space for "Full Control" & "Full Read".

Set-WebAppUserPolicy $wa $SuperUserAcc "Super User (Object Cache)" "FullControl"
$wa.Properties["portalsuperreaderaccount"] = $SuperReaderAcc
Set-WebAppUserPolicy $wa $SuperReaderAcc "Super Reader (Object Cache)" "FullRead"

 

Nov 8, 2011 at 1:15 PM

Thanks for your job !

Let me just add some information.

I have an error in the "CreateMetadataServiceApp" and "CreateUserProfileServiceApplication" functions because of the "$AdminPort" that is not known by the script.

I think you should use "$CentralAdminPort" instead of "$AdminPort".

Coordinator
Dec 17, 2011 at 4:34 AM

Hi everyone, I've finally gotten around to start implementing some of these great contributions. The first will be:

$builtinAdminGroup = (Get-WmiObject -Class Win32_Group -computername $env:COMPUTERNAME -Filter "SID='S-1-5-32-544' AND LocalAccount='True'" -errorAction "Stop").Name

So as to not hard-code the Administrators group in English. Great suggestion and looking to include in the next release.

Brian

Feb 1, 2012 at 2:33 PM
Edited Feb 2, 2012 at 8:21 AM

Thank you so much for your help ! Let me just add some information,

I have a new error, on Function AddResourcesLink when try con iclude a new element on list "Resources". Change it to (spanish):

Function AddResourcesLink([string]$title,[string]$url)
{
	$centraladminapp = (Get-spwebapplication -includecentraladministration | where {$_.DisplayName -eq "SharePoint Central Administration v4"});
	$centraladminurl = $centraladminapp.Url
	$centraladmin = (Get-SPSite $centraladminurl)

	# Edit *Lang Hack*
	if(!$AdminLCID)
	{
		$AdminCulture = $(Get-SPWeb $centraladminurl).UICulture
		$AdminLCID = $AdminCulture.LCID
		Write-Host " - Central Admin Lang : "+$AdminCulture.DisplayName+" ($AdminLCID)"
	}
	switch($AdminLCID)
	{
		#3082: es-ES
		3082 
		{
			$item = $centraladmin.RootWeb.Lists["Recursos"].Items | Where { $_["URL"] -match ".*, $title" }
		}	
		default
		{
			$item = $centraladmin.RootWeb.Lists["Resources"].Items | Where { $_["URL"] -match ".*, $title" }
		}
	}
		
	If ($item -eq $null )
	{
		switch($AdminLCID)
		{
			#3082: es-ES
			3082 
			{
				$item = $centraladmin.RootWeb.Lists["Recursos"].Items.Add();
			}	
			default
			{
				$item = $centraladmin.RootWeb.Lists["Resources"].Items.Add();
			}
		}		
	}

	$url = $centraladminurl + $url + ", $title";	
	$item["URL"] = $url;
	$item.Update();
}
Traduction for the other ones (Spanish installation):

CreateMetadataServiceApp

 #3082: es-ES
 3082 
 {
  Grant-SPObjectSecurity $MetadataServiceAppSecurity -Principal $AccountPrincipal -Rights "Acceso total al almacén de términos"
 } 

CreateUserProfileServiceApplication  

 #3082: es-ES
 3082 
 {
  # Give 'Full Control' permissions to the MySite App Pool and Portal App Pool account claims principals
  Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $MySiteAppPoolAcctPrincipal -Rights "Control total"
  Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $PortalAppPoolAcctPrincipal -Rights "Control total"
  # Give 'Retrieve People Data for Search Crawlers' permissions to the Content Access claims principal
  Grant-SPObjectSecurity $ProfileServiceAppSecurity -Principal $ContentAccessAcctPrincipal -Rights "Recuperar datos de personas para los rastreadores de búsqueda"
 }  
Apr 10, 2012 at 11:46 AM

@Brian: It looks like the AutoSPInstaller needs languagepacks too. :)

I think adding some language definition files is the solution.

A thing to keep in mind is that the culture can be configured per site (eg. mysites).