Harald S. Fianbakken on December 19th, 2013

You can easily use custom build phases to customize your application build & signing in xcode.

Do the following:

  • Goto your project settings
  • Click your selected build target (e.g. MyApplication)
  • Go to the “Build phases” tab
  • In the top-menu bar (Mac), click the “Editor” -> Add Build Phase -> Run Script build phase
  • Double click the “run script” name to rename your build phase
  • Add a custom script (shell/ruby/etc).
  • Want other variables / dynamic builds etc?
    • Add a custom variable to your build
    • Click build settings
    • Click “Editor” (Top-menu)
    • Click “Add build setting” – User defined
    • Name your variable (e.g. MY_VAR)

Example script showing the project name, scheme being built and the custom build variable (e.g. skin):

echo "warning: TARGET IS ${TARGET_NAME}"
echo "warning: SIGNING IS ${CODE_SIGN_IDENTITY}"
echo "warning: PROVISIONING is ${PROVISIONING_PROFILE}"
echo "warning: APP: ${TARGET_BUILD_DIR}/${TARGET_NAME}.app/"
echo "warning: CUSTOM VAR ${MY_VAR}"

exit 0
									

If you build your project from Xcode, you’ll see the warning messages in the build warning/errors, along with the full output if you click one of the messages.

Now, if you want to run your xcode build from command line / bash and change your variable (MY_VAR)

Run the following (modified for workspace build):

xcodebuild -workspace MyWorkspace.xcworkspace -scheme MyApp MY_VAR=”MY awsome skin”

What can you use this for? Some examples

  • Custom skinning of your app
    • Multiple skins for same app, different app names, rules, variables, resources etc.
  • Custom signing for your app
    • 1 codebase, different signing / application name etc.
  • Conditional builds
    • Adding conditional paths and styling and rules for variables.

Tags: , , , ,

Harald S. Fianbakken on December 10th, 2013

If you recently upgraded to Xcode 5 or you have some old buildscripts which haven’t been running in a while, you might have encountered the following error:

“object file format invalid or unsuitable” or “can’t exec ‘codesign’ (No such file or directory)”

Does your buildscript point to :

  • /Applications/Xcode.app/Contents/Developer/usr/bin/codesign_allocate

It seems the path have changed in Xcode5. Changing the path in our build scripts didn’t work OOTB as there were more issues.

The following did the trick to make it work on our solution:
Symlink the latest codesigning allocate to the expected path:

  • sudo mv /usr/bin/codesign_allocate /usr/bin/codesign_allocate_old
  • ln -s /usr/bin/codesign_allocate /Applications/Xcode.app/Contents/Developer/usr/bin/codesign_allocate

Tags: , , , ,

Harald S. Fianbakken on December 10th, 2013

A little bash-fun for manipulating values from a XML-file. E.g. an Android resource file (or multiple of resource files)

FILE="resources.xml"
# Get the value from <string name="app_name"> in a config file
# Using grep and unescaping the value (assuming value is escaped)
APPNAME=$(cat $FILE|grep app_name|xmlstarlet sel -t -v '.'|xmlstarlet unesc)

# Better - Use only xmlstarlet

APPNAME=$(xmlstarlet sel -t -v "//resources/string[@name='app_name']" $f)

									

Manipulating values in the file using XPATH

#Update the app name in the FILE

xmlstarlet ed -L -u "//resources/string[@name='app_name']" -v "New app-name" $FILE

# Remove the APP_TYPE string from the file
xmlstarlet ed -L -d "//resources/string[@name='APP_TYPE']" $FILE

									

For the bash-newbies; if you’d like to replace or update a set of these files, wrap it in a find:

# Simple wrapper - Find all xml-files with name and replace content in them
FILES=$(find . -name constants.xml)

for FILE in $FILES; do
   # Use XMLStartlet the similar way
done;
									

Tags: , ,

Harald S. Fianbakken on September 28th, 2013

Getting MSDeploy (Web deploy) to work from Visual Studio 2012 using MSDeploy on your server is fairly easy, as long as you know what to install and what URL’s to use.

A quick howto-guide:

On your server:

  1. Install MSDeply on your Windows Server (http://www.iis.net/download/webdeploy)
  2. Run the installer (MSI)
  3. The instance will default run on http://server:80/MSDEPLOYAGENTSERVICE
  4. Note the sites you want to publish for (site names)

In visual studio, configure a publishing target:

  1. In the server field, type http://server:80/MSDEPLOYAGENTSERVICE
  2. If you leave out :80/MSDEPLOYAGENTSERVICE , the connection will not succeed
  3. Set the site name for your publishing profile
  4. Set your username/password that can log in to the server
  5. Validate connection

Voilà, you can now publish directly from Visual Studio 2012 to your remote old Win2003 server;)

Tags: , , ,

Harald S. Fianbakken on September 9th, 2013

Xcode will keep old archive when building indefinite, unless you explicitly delete them. This can be a problem on e.g. your build server, running it’s disk full.

I made this little script you can run to do a clean up of archives older than 7 days:

#!/bin/bash
for i in `find /Users/myUser/Library/Developer/Xcode/Archives -maxdepth 1 -type d -mtime +7 -print`; do echo -e "Deleting archive $i"; rm -rf $i; done
									

Remember to replace the path to your user running the build scripts.

Tags: , , ,

Harald S. Fianbakken on June 4th, 2013

I created the following little wrapper to be able to export/import settings from your Site collection on Sharepoint 2013. It takes your search site collection url, and export it to a readable/editable XML file and allows for you to import it again.

You can easily modify it to export/import for your SSA/Web by changing the exportLevel.

[reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null
[reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.search") | Out-Null


function Export-SPEnterpriseSearchSettings($siteUrl, $settingsFile="SearchSchema.xml", $exportLevel=[Microsoft.SharePoint.Client.Search.Administration.SearchObjectLevel]::SPSite){

    
    $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
    $searchConfigurationPortability = New-Object Microsoft.SharePoint.Client.Search.Portability.SearchConfigurationPortability($context)
    $owner = New-Object Microsoft.SharePoint.Client.Search.Administration.SearchObjectowner($context,$exportLevel)
    $value = $searchConfigurationPortability.ExportSearchConfiguration($owner)
    $context.ExecuteQuery()
    [xml]$schema = $value.Value
    $schema.OuterXml | Out-File $settingsFile -Encoding UTF8
}


function Import-SPEnterpriseSearchSettings($siteUrl, $settingsFile="SearchSchema.xml", $exportLevel=[Microsoft.SharePoint.Client.Search.Administration.SearchObjectLevel]::SPSite){
    
    $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
    $searchConfigurationPortability = New-Object Microsoft.SharePoint.Client.Search.Portability.searchconfigurationportability($context)    
    $owner = New-Object Microsoft.SharePoint.Client.Search.Administration.searchobjectowner($context,$exportLevel)
    [xml]$schema = [xml](gc $settingsFile)
    $searchConfigurationPortability.ImportSearchConfiguration($owner,$schema.OuterXml)
    $context.ExecuteQuery()
}
									

Inspired from Anders Rask’s approach of using the client-side dll. Check out Anders blog-post for more details for the schema being exported.

 

Tags: , ,

Harald S. Fianbakken on June 3rd, 2013

For some reason, Microsoft didn’t create a handy method for extracting user info from their own property.

If you output the managed property EditorOWSUser, you are left with a bizarre (and not user friendly) string such as:
some.email@somedomain|Some User FullName|0aabcbbaabdbdbbbfbebbebe01010f0f0;|##ClaimsToken

What most users want, is to simply display the user name (or email). I created a small script you can add on top on your displaytemplate to do just this (or bundle in your own JS files) as we don’t like repeating ourselves.

    function getUserComponent(data, component){
      if(component===undefined){
      
        component = 'name';
      }
      var editorEmail = "";
      var editorDisplayName ="";
      if(!$isEmptyString(data)){
              var editorIdentifiers = data.split(" | ");
          
          if(!$isNull(editorIdentifiers[0])){
               editorEmail = editorIdentifiers[0];
            }
            if(!$isNull(editorIdentifiers[1])){
               editorDisplayName = editorIdentifiers[1];
            }
      }
    
      if(component == 'email'){
        return editorEmail;
       } else if(component == 'name'){    
        return editorDisplayName;
      } else{
        return "Invalid component!!.."
      }
    }


									

Sample usage, show a list item with the modified date and by whom modified it.

<!--#_ if(ctx.CurrentItem.LastModifiedTime !== undefined && ctx.CurrentItem.LastModifiedTime !== null) { _#-->
            <li><strong>Modified:</strong> _#= ctx.CurrentItem.LastModifiedTime =#_ by _#= getUserComponent(ctx.CurrentItem.EditorOWSUSER)=#_ </li>              
<!--#_  } _#-->  
									

Tags: , , ,

Harald S. Fianbakken on April 12th, 2013

The installation kept failing on the pre-requisites AppFabric. By inspecting the logfile, the error code was 1603 – generic error.

I tried downloading the seperate 1.1. appFabric installer (x64), but it also kept throwing the same exception. After googling around; it turns out that this is a common problem.

Most suggestions resulting in solving this suggested removing the PsModulePath from the system environments variable or adding %systemroot%\WindowsPowershell\1.0\ to your path. However, none of the above worked for my environment;

After a long while; I got the enviroment up running;

The following steps will prolly do the trick on your machine aswell if you have the same issue:

* Remove your PSModulePath from System Environments variable
* Uninstall any versions of AppFabric (Programs & Features – Remove, select all for removal)
* Make sure there’s nothing left of app fabric in your gac (you’ve uninstalled, but for my case, some of the files remained in the GAC)
* Download the AppFabric installer and extract it do a safe location – E.g C:\temp\AppFabric\
* Reinstall with all the features in same install (remember to run installer as administrator)

Hopefully will save some of you a lot of time.

Tags: , , ,

Harald S. Fianbakken on April 1st, 2013

I tried restoring one of my old databases (SQL 2008) to my LocalDB (SQLExpress 2012).

It failed brutally with the following message: “Property backupdirectory is not available for settings”.

After playing around a while, I added the property to the registry. However, the problem didn’t end there. It turns out quite a few keys are missing.

To solve the problem and to be able to restore your database into your LocalDB, do the following:

  1. Launch regedit
  2. Goto HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Your_SQL_Instance_Name\MSSQLServer
  3. Add the following keys (String-value): BackupDirectory, DefaultData, DefaultLog, MasterDBPath
  4. Edit their values to a resonable location (e.g. C:\SQLBackup\)

Restore your database.

Tags: , ,

Harald S. Fianbakken on March 27th, 2013

I finally got some time and put the SharePointations on NuGet. I’ve created a seperate page for this project with some examples and some brief documentation.

I’ll put up some more examples and details later. You can fetch the framework from Nuget.Org and start playing with it yourself meanwhile.

Quick start:

  1. Create a class library
  2. Install the Sharepointations using nuget (install-package Fianbakken.Sharepointations
  3. Annote your pocos (E.g. [ContentType] on classes, and [ContentTypeField] on fields)
  4. Build your class library
  5. Run one of the custom tools to install your content type into sharepoint.

Tags: , , , ,