Archives

Archives / 2007
  • SharePoint stsadm.exe and the infamous "Command line error"

    The SharePoint command-line utility stsadm.exe was driving me crazy for the last two days. I'm automating all kind of this from PowerShell scripts, but I got the error "Command line error" while I was absolutely sure that what I was doing was correct. I did stsadm.exe -o deletesolution foobar.wsp. And the problem was: character encoding...

    First I thought it was a problem with the way I executed this command from PowerShell. When I copied over the command to a different script it worked. What!!!??? Then I copied it over to the cmd.exe shell on the command line and I got the same error.

    I started searching on Google and came accross this blogpost. It said it had something to do with encoding. The blog post also pointed to this blog post where people responded in the contents with the most hillarious solutions like:

    If I type STSADM.EXE it works, while STSADM.exe does not work, or that a solution file must be in the same folder as stsadm.exe. Read the comments, it is fun how far off people can get.

    Another post mentioning the problem is this discussion thread.

    The problem happened to be in the encoding. One way or the other it is possible to get different encodings while typing in the same command multiple times in the same cmd.exe shell. Don't ask me how.

    If you have problems, type your text in an editor like Notepad++, and switch between "Encode in ANSI" and "Encode in UTF-8" (it is under the Format menu in Notepad++). You see (sometimes)the dash(-) in stsadm -o command... change from '-' to a strange little block... There is the problem. The dash is not always a dash, it is a hyphen... And stsadm then thinks that no command is specified. Remove the strange block, type a hyphen while is UTF-8 encoding, copy that and bingo!! It works.

    Ok, how to repeat this:

    1. Start Notepad++, set encoding to ANSI
    2. Make sure the path to stsadm.exe is in your path environment variable (or use full path)
    3. Type stsadm -o deletesolution foobar.wsp
    4. Start cmd.exe
    5. Copy the text over and press enter: voila, Command line error.

    The strange thing is that even if you remove the dash (-), and type it again, it still gives errors. I have no clue why.

    This dash/hypen thing is a common problem if you search Google, for more info see for example:

  • The future of Domain Specific Languages on the Visual Studio platform

    Now Visual Studio 2008 is released (I know, I'm blogger #100.000 to mention this) it is interesting to look at the future of one of the important building blocks on the Microsoft platform for building Software Factories: the DSL Tools.

    Stuart Kent, Senior Program Manager with the Visual Studio Ecosystem team, reveals a part of the post Visual Studio 2008 roadmap for the DSL tools in its blog post DSL Tools beyond VS2008.

    Some of the mentioned concepts are already available in the implementation of the Web Service Software Factory: Modeling Edition, really interesting to have a look at the code.

    The next version of Visual Studio will be Rosario. Clemens Rijnders describes some of the new Rosario features with respect to DSLs in his blog post Rosario Team Architect CTP10 Preview. One promising concept is the Designer Bus, which should simplify working with multiple DSLs in the same domain that reference each other. Some support for this functionality in currently available as the DSL integration service power toy.

  • PowerShell Exception handling using "Trap" explained - links

    PowerShell has powerful exception handling, but it is badly documented and takes while to understand what the heck they actually want to do to wire up the exception handling.

    I'm normally not such a link poster, this is more of a "post-to-self" item that might be useful for others as well.

  • The P&P Web Service Software Factory modeling edition and the Secret Dutch Software Factory Society

    It is final! After almost nine months of hard work the version 3 of the Patterns&Practices Service Factory is released on CodePlex.

    Johan Danforth already published this announcement here, but it doesn't hurt to bring it to your attention again because this stuff is good!

    And the strange thing is that Don Smith, the Technical Product Planner of the Service Factory didn't had the time to blog about it and announce it officially. But I know why: he is a busy man! After TechEd 2007 in Barcelona last week (interview video), he was so kind to take the time to repeat the 3-days Service Factory Customization Workshop in the Netherlands with the Secret Dutch Software Factory Society.

    I heard about this workshop through Olaf Conijn, who used to work at our great company Macaw. He announced the Dutch workshop in this blog post.

    Olaf and Don did give this fantastic workshop at the domains of InfoSupport in Veenendaal, the Netherlands (thanks for the hospitality Marcel!). Way to far away from home (okay 80km in the Netherlands is trouble in the morning and afternoon), so a good reason to take a hotel and continue in the evenings where you often have the best conversations about beer, woman, and... oh ya, software factories.

    Don and Olaf are great guys who know their stuff, and they even both did Bikram yoga, my addiction in life;-)

    I personally wasn't really that interested in the web services part of the Web Service software factory, but in the customization part. And that is what we did. We customized the factory without "cracking the factory" (change the source code) through the great extensibility points that are available, and customized it while "cracking the factory" and changing the code. And the good thing is: this scenario is supported, documented and it is actually expected behavior to be done by companies who will be using the Service Factory;-). And the brilliant thing is: they even provided the code to build a complete MSI installer for your modified Service Factory!

    The factory is provided with complete (recompileable) source code, and contains a lot of really interesting factory plumbing that I will elaborate on in a later post.

    One thing is sure: we are definitely going to integrate the Web Service Software Factory into the Macaw Solutions Factory, our own software factory. It will fit like a glove (after some customization of course;-)). Brilliant work P&P!

    Another great thing of three days together with 25 people busy with software factories is the amount of collective knowledge and the wealth of information we did share with each other. My compliments to Don and Olaf for providing a lot of room for this information sharing.

    We gave presentations to each other about the things we are doing with software factories:

    For more information see the MSDN landing page Web Service Software Factory: Modeling Edition. Check it out!

  • Powershell: Is a SharePoint solution installed or deployed?

    I was having some fun with PowerShell to talks against the SharePoint object model. I needed to know if a SharePoint solution was installed and if it was deployed. I got to the code below. Might be handy for someone to see how easy it is to get info out of SharePoint.

    And the purpose I need it for? In our Macaw Solutions Factory we have a development build and a package build. Development build for SharePoint deploys everything to the bin folder of one or more web applications. Package build creates a solution package (.wsp file) that does install assemblies to the GAC. If this solutions package is deployed on the development machine, we want to detect that, because you will not see any changes after compile in a development build. The GAC assemblies have precedence over the assemblies in the web application bin folder.

    So here is the code, have fun with it.

    [void][reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint")
    

    function global:Test-SharePointSolution { param ( $solutionName = $(throw 'Missing: solutionName'), [switch]$installed, [switch]$deployed )

    </span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)"> (</span><span style="color: rgb(0,0,0)">!</span><span style="color: rgb(0,0,0)">(</span><span style="color: rgb(0,0,255)">$solutionName</span><span style="color: rgb(0,0,0)">.EndsWith(</span><span style="color: rgb(0,0,128)">'</span><span style="color: rgb(0,0,128)">.cab</span><span style="color: rgb(0,0,128)">'</span><span style="color: rgb(0,0,0)">) </span><span style="color: rgb(0,0,0)">-</span><span style="color: rgb(0,128,128)">or</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$solutionName</span><span style="color: rgb(0,0,0)">.EndsWith(</span><span style="color: rgb(0,0,128)">'</span><span style="color: rgb(0,0,128)">.wsp</span><span style="color: rgb(0,0,128)">'</span><span style="color: rgb(0,0,0)">) </span><span style="color: rgb(0,0,0)">-</span><span style="color: rgb(0,128,128)">or</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$solutionName</span><span style="color: rgb(0,0,0)">.EndsWith(</span><span style="color: rgb(0,0,128)">'</span><span style="color: rgb(0,0,128)">.wpp</span><span style="color: rgb(0,0,128)">'</span><span style="color: rgb(0,0,0)">)))
    {
        throw </span><span style="color: rgb(0,0,128)">"</span><span style="color: rgb(0,0,128)">solution name '$solutionName' should end with .cab, .wsp or .wpp</span><span style="color: rgb(0,0,128)">"</span><span style="color: rgb(0,0,0)">
    }
    
    </span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)"> (</span><span style="color: rgb(0,0,255)">$installed</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,0)">-</span><span style="color: rgb(0,128,128)">and</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$deployed</span><span style="color: rgb(0,0,0)">)
    {
        throw </span><span style="color: rgb(0,0,128)">"</span><span style="color: rgb(0,0,128)">Select either the '-installed' switch parameter or the '-deployed' switch parameter, not both at the same time</span><span style="color: rgb(0,0,128)">"</span><span style="color: rgb(0,0,0)">
    }
    
    </span><span style="color: rgb(0,0,255)">$farm</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"> [Microsoft.SharePoint.Administration.SPFarm]::get_Local()
    </span><span style="color: rgb(0,0,255)">$solutions</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$farm</span><span style="color: rgb(0,0,0)">.get_Solutions()
    </span><span style="color: rgb(0,0,255)">$solutioncheck</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$false</span><span style="color: rgb(0,0,0)">
    </span><span style="color: rgb(0,0,255)">foreach</span><span style="color: rgb(0,0,0)"> (</span><span style="color: rgb(0,0,255)">$solution</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">in</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$solutions</span><span style="color: rgb(0,0,0)">)
    {
        </span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)"> (</span><span style="color: rgb(0,0,255)">$solution</span><span style="color: rgb(0,0,0)">.Name </span><span style="color: rgb(0,0,255)">-ieq</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$solutionName</span><span style="color: rgb(0,0,0)">)
        {
            </span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)"> (</span><span style="color: rgb(0,0,255)">$deployed</span><span style="color: rgb(0,0,0)">)
            {
                </span><span style="color: rgb(0,0,255)">$solutioncheck</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"> </span><span style="color: rgb(0,0,255)">$solution</span><span style="color: rgb(0,0,0)">.Deployed
            }
            </span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">
            {
                </span><span style="color: rgb(0,128,0)">#</span><span style="color: rgb(0,128,0)"> installed, is always true if we get here</span><span style="color: rgb(0,128,0)">
    

    $solutioncheck = $true } break } } return $solutioncheck }

    Test-SharePointSolution -solutionName wikidiscussionsolution.wsp -installed Test-SharePointSolution -solutionName wikidiscussionsolution.wsp -deployed

  • PowerShell: Creating a SharePoint solution package (WSP file) with CAS

    I need to add some code access security information to a SharePoint solution package manifest file. Given the assembly file we can retrieve the required assembly info, and with some xml magic in PowerShell create some result xml. It is not actually the exact code I use in my solution, but it shows the job...

    # function: GetAssemblyInfo
    #
    Arguments: $assemblyFile - path to assembly file to determine information from
    #
    Returns: Hashtable with the following keys: PublicKeyBlob, Name, Version
    function global:GetAssemblyInfo
    {
        param
        (
           
    $assemblyFile = $(Throw'Missing: assemblyFile')
        )
       
       
    if (!(Test-Path -Path $assemblyFile))
        {
            Throw
    "Assembly file '$assemblyFile' does not exist"
        }
       
       
    # Secutil returns:
       #Line 0: Microsoft (R) .NET Framework SecUtil 2.0.50727.42
       #Line 1: Copyright (c) Microsoft Corporation.  All rights reserved.
       #Line 2:
       #Line 3: Public Key =
       #Line 4: 0x00240000048000009400000006020000002400005253413100040000010001003BBC200DC39F9419851471C4AF65A91540C5904D72694CDE6DF63427FAD8D180630538338E557D90BA4F18A2EF6F44F3A53A5C7CFE625F4954D53B4FF9CF700226FDF13F04731EDED323B1821BA38C5F310231007E7AF862F497174A127BD42C0FA4FAFF1154910B48E177E090888A7745145ED4F4F7BB75D28D6616961A71E3
       #Line 5: Name =
       #Line 6: Macaw.Mast.Wss3.Templates.Presentation.WebAppUI
       #Line 7: Version =
       #Line 8: 1.0.0.0
       #Line 9: Success
       $secutilExe = 'C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\SecUtil.exe'

       
    $resultLines = (& $secutilExe -hex -s $assemblyFile)
       
    if ($resultLines[9]-ne 'Success')
        {
            Throw
    "secutil.exe can't determine assembly information from assembly file '$assemblyFile', secutil.exe command failed"
        }
        @{
    'PublicKeyBlob' = $resultLines[4];'Name' = $resultLines[6];'Version' = $resultLines[8] }
    }

    $assemblyFile = 'C:\Inetpub\wwwroot\wss\VirtualDirectories\1000\bin\Macaw.Mast.Wss3.Templates.Presentation.WebAppUI.dll'
    $result = GetAssemblyInfo -assemblyFile $assemblyFile
    $result

    This will result in the following output:

    We can now create out code access security information (in this case in a SharePoint solution package manifest.xml file with code similar to the following code:

    $assemblyInfo = GetAssemblyInfo -assemblyFile $assemblyFile
    $policyItem = @"
    <PolicyItem>
        <PermissionSet class="NamedPermissionSet" version="1" Description="Macaw Solution Factory generated permissionSet" Name="$($assemblyInfo.Name)-PermissionSet">
            <IPermission class="WebPermission" version="1">
                <ConnectAccess>
                    <URI uri="`$OriginHost`$" />
                </ConnectAccess>
            </IPermission>
            <IPermission class="SmtpPermission" version="1" Access="Connect" />
            <IPermission class="SharePointPermission" version="1" ObjectModel="True" />
            <IPermission class="PrintingPermission" version="1" Level="DefaultPrinting" />
            <IPermission class="FileIOPermission" version="1" Read="`$AppDir`$" Write="`$AppDir`$" Append="`$AppDir`$" PathDiscovery="`$AppDir`$" />
            <IPermission class="EnvironmentPermission" version="1" Read="TEMP;TMP;USERNAME;OS;COMPUTERNAME" />
            <IPermission class="SqlClientPermission" version="1" Unrestricted="true" />
            <IPermission class="SecurityPermission" version="1" Flags="Assertion, Execution, ControlThread, ControlPrincipal, RemotingConfiguration" />
            <IPermission class="DnsPermission" version="1" Unrestricted="true" />
            <IPermission class="WebPartPermission" version="1" Connections="True" />
            <IPermission class="AspNetHostingPermission" version="1" Level="Medium" />
            <IPermission class="IsolatedStorageFilePermission" version="1" Allowed="AssemblyIsolationByUser" UserQuota="9223372036854775807" />
        </PermissionSet>
    <Assemblies>
    	<Assembly Name="$($assemblyInfo.Name)" Version="$($assemblyInfo.Version)" PublicKeyBlob="$($assemblyInfo.PublicKeyBlob)" />
    </Assemblies>
    </PolicyItem>
    "@
    
    $xmltext = @"
    <?xml version="1.0" encoding="utf-8"?>
    <Solution DeploymentServerType="WebFrontEnd" SolutionId="2244989E-9DA9-4a5d-9767-0D8F387181B7" ResetWebServer="true">
        <CodeAccessSecurity>
        </CodeAccessSecurity>
    </Solution>
    "@
    
    [xml]$xmlDoc = $xmltext
    $xmlDoc.SelectSingleNode('/Solution/CodeAccessSecurity').set_InnerXml($policyItem)
    $xmlDoc.get_InnerXml()
    

     

    This will results in the following output:

    In the production of a real SharePoint solution package a lot more is happening, but this showcases some of the PowerShell power you can use to get the job done.

  • Visual Studio SDK 4.0, Vista and symbolic links...

    When you install Visual Studio SDK on Vista, it doesn't install by default on X:\Program Files, but on X:\Program Files (x86).

    When I tried to recompile the VSIP Software Factory from Codeplex, it had links to the Visual Studio SDK in c:\program files.

    Instead of moving things around I created a symbolic directory link:

    mklink  /D "Visual Studio 2005 SDK" "c:\Program Files (x86)\Visual Studio 2005 SDK"

    Works like a breeze!

     

     

  • SharePoint: Custom Field Type for MultiLine text

    When you add a custom field type that can hold more than the 255 characters you can't use a field of type SPFieldText because it has a max length of 255 characters.

    An obvious candidate is to use the field type SPFieldMultiLineText. No problems so far. But... in your custom version of the fldtypes.xml file (for example fldtypes_mytypes.xml) you have to define your parent type of the custom field. You would expect a parent type named MultiLineText, but no, that would be too obvious. It should be Note. Not documented, such a pity...

    For example:

    <?xml version="1.0" encoding="utf-8" ?>
    <
    FieldTypes>
        <
    FieldType> <Field Name="TypeName">LongText</Field>
            <
    Field Name="ParentType">Note</Field>
            <
    Field Name="TypeDisplayName">Long Text</Field>
            <
    Field Name="TypeShortDescription">Long Text</Field>
            <
    Field Name="UserCreatable">TRUE</Field>
            <
    Field Name="Sortable">FALSE</Field>
            <
    Field Name="AllowBaseTypeRendering">TRUE</Field>
            <
    Field Name="Filterable">FALSE</Field>
            <
    Field Name="FieldTypeClass">...full qualified class,assembly name...</Field>
            <
    PropertySchema>
                <
    Fields></Fields>
            </
    PropertySchema>
            <
    RenderPattern Name="DisplayPattern">
                <
    Column/>
            </
    RenderPattern>
        </
    FieldType>
    </
    FieldTypes>

    A link with some more info (in Spannish): http://www.ideseg.com/SharePointDestripandoElWiki4.aspx

  • Generate a list of GUID's

    Sometimes you just need a lot of GUID's while programming.  Ofcourse you could use the Visual Studio GUID tool, bu that is a lot of work.

    Open a PowerShell console, and paste in the following line to get a list of 100 guid's:

    $i=100; while ($i-- -gt 0) { Write-Host ([System.Guid]::NewGuid()) }

  • Factories @ Macaw - the DotNed presentation of april 26, 2007

    On april 26, 2007 I gave a presentation at the Macaw headquarters in Schiphol-Rijk, The Netherlands on what we are doing with Software Factories at Macaw.

    I promised the audience to publish some links to tools and information mentioned in the presentation. I can't upload the presentation itself because it was a real "look into the kitchen of..." session with information that we can't give away (yet). I promise to blog more on this in the future however.

    Some initial posts on what we are working on:

    Tools we are using to realize our software factory vision:

    I hope you all had an informative session and got some "food for thought" ob what you could do within your organization. If you would like to leave a comment on what your impression of the presentation, please do so as a comment to this blog post, or send me a direct e-mail at serge@macaw.nl!

  • SharePoint Features - elements, scope and other info

    When designing features for SharePoint 2007 you always have to think about the scope where the feature should be executed: Web, Site, WebApplication or Farm. Microsoft has a nice table in its documentation that gives insight in what can be done where. Bram, thanks for pointing this out to me!! For more information on what these features do see this documentation by microsoft. Below I do some hyperlinking/annotation on this information to give you quick(er) access to the wonderful world named features...

    The article is not finished yet, I would like to link to interesting blog posts etc, but don't have the time right now. It might be useful as it is right now. If you have other info to link in, let me know (as a comment) and I will update the post.


    SCOPE AND ALLOWED FEATURES

     

     

    Web (Web site)

    Site (site collection)

    WebApplication (Web application)

    Farm (farm)


    DETAILED EXPLANATION OF THE FEATURES

     

     

    Content Type (Site)

    Contains a schema definition you can reuse and apply to multiple list definitions.

    Links:


     

    Content Type Binding (Site)

    Content type binding enables you to provision a content type on a list defined in the onet.xml schema. Lists defined in the onet.xml schema cannot be modified directly.

    Links:


    Control (Farm, WebApplication, Site, Web)

    A delegate control contains a registration for a well-known control installed on a Web page. This lets you replace existing controls, such as the Windows SharePoint Services search control, with another control.

    Links:


    Custom Action (Farm, WebApplication, Site, Web)

    You can define the following kinds of custom actions:

    • Content type links for the content type settings page

    • Drop-down menu actions for the drop-down menu that appears for an item

    • Form toolbar buttons for New, Edit, or Display form toolbars.

    • Site Settings link for the Site Settings page.

     In a custom action it is often required to pass context arguments on the URL in the <UrlAction> tag. This in done with URL Tokens.

    The following URL tokens are supported:

    Windows SharePoint Services supports the following tokens with which to start a relative URL:

    • ~site - Web site (SPWeb) relative link.
    • ~sitecollection - site collection (SPSite) relative link.

    In addition, you can use the following tokens within a URL:

    • {ItemId} - Integer ID that represents the item within a list.
    • {ItemUrl} - URL of the item being acted upon. Only work for documents in libraries. [Not functional in Beta 2]
    • {ListId} - GUID that represents the list.
    • {SiteUrl} - URL of the Web site (SPWeb).
    • {RecurrenceId} - Recurrence index. This token is not supported for use in the context menus of list items.

    Procedures

    Links:


    Custom Action Group (Farm, WebApplication, Site, Web)

    Defines a group of custom actions.

    Links:


    Document Converter (WebApplication)

    Contains the definition of a document converter. A document converter is a custom executable file that takes a document of one file type, and generates a copy of that file in another file type.


    Feature/Site Template Association (Farm, WebApplication, Site)

    Binds a feature to a site definition or template so that created sites are provisioned with the feature.


    Field (Site)

    Contains a field definition that can be reused among multiple lists.


    Hide Custom Action (Farm, WebApplication, Site, Web)

    Hides a custom action that has been added through another custom action.

    Links:


    List Instance (Site, Web)

    Provisions a SharePoint site with a specific list of data.


    List Template (Site, Web)

    Contains a list definition or template, which defines a list that can be provisioned in a SharePoint site.


    Module (Site, Web)

    Contains a set of files with which to provision sites.


    Receiver (Web)

    Contains an item event receiver registration.


    Workflow (Site)

    Contains the definition for a workflow in a list.

     


    OTHER INTERESTING INFORMATION 

     

    Features and element files

    In order to ensure that the feature can be properly upgraded all files belonging to the feature should be included in <ElementFile> tags. If files are not properly defined in <ElementFile> tags they will not always be upgraded when the feature is upgraded. [Source: Jussi Palo]


    OTHER LINKS 

     

    Activation Dependencies and Scope - How dependency between features is handled in the context of scope

  • MsBuild: sort your Content item file names

    I have been playing a bit with MsBuild to process a set of Content items sorted by file name. Content items are the items included in the project, and their Build Action set to Content. Below some sample code on how to achive this, just paste the code in a file sorttest.msbuild, and run as msbuild.exe sorttest.msbuild.

     

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="SortTest"
        xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
    

    <PropertyGroup> <SortCommand>$(WinDir)\System32\sort.exe</SortCommand> <ContentItemsSortInFile>$(TEMP)\sortfileIn.tmp</ContentItemsSortInFile> <ContentItemsSortOutFile>$(TEMP)\sortfileOut.tmp</ContentItemsSortOutFile> </PropertyGroup>

    <ItemGroup> <Content Include="SampleNorthwind\0002_content.testdata.sql" /> <Content Include="SampleNorthwind\0001_initial.schema.sql" /> <Content Include="SampleNorthwind\0004_employee-mobilephone.schema.sql" /> <Content Include="SampleNorthwind\0003_constraints.schema.sql" /> </ItemGroup>

    <Target Name="SortTest"> <WriteLinesToFile File="$(ContentItemsSortInFile)" Lines="@(Content)" Overwrite="true"/> <Exec Command="$(SortCommand) $(ContentItemsSortInFile) > $(ContentItemsSortOutFile)"/> <ReadLinesFromFile File="$(ContentItemsSortOutFile)"> <Output TaskParameter="Lines" ItemName="SortedContent"/> </ReadLinesFromFile> <!-- CLEAN UP TEMPORARY FILES --> <Delete Files="$(ContentItemsSortInFile)"/> <Delete Files="$(ContentItemsSortOutFile)"/>

    &lt;!--</span><span style="color: rgb(0,128,0)"> DO YOUR ACTION WITH SortedContent, FOR NOW, JUST WRITE IT OUT, ',' SEPARATED </span><span style="color: rgb(0,0,255)">--&gt;
    &lt;</span><span style="color: rgb(163,21,21)">Message</span><span style="color: rgb(0,0,255)"> </span><span style="color: rgb(255,0,0)">Text</span><span style="color: rgb(0,0,255)">=</span>"<span style="color: rgb(0,0,255)">@(SortedContent,',')</span>"<span style="color: rgb(0,0,255)">/&gt;
    

    </Target> </Project>

    UPDATED:

     

    My collegue Dion Olsthoorn came with the following solution that is smarter:

    • Get the files from filesystem, is sorted by default
    • Determine all files NOT in project
    • Get again files from filesystem, exclude files NOT in project
    • Result is a set of sorted items as included in the project (as Content items)

    Nifty nifty!

    Replace this target in the code above:

    <Target Name="SortTest" Outputs="%(Content.RelativeDir)">

                    <CreateItem Include="%(Content.RelativeDir)*" Exclude="@(Content)">

                                   <Output TaskParameter="Include" ItemName="ExcludedSortedContent"/>

                    </CreateItem>

                    <CreateItem Include="%(Content.RelativeDir)*" Exclude="@(ExcludedSortedContent)">

                                   <Output TaskParameter="Include" ItemName="SortedContent"/>

                    </CreateItem>

                    <Message Text="@(SortedContent,',')" />

    </Target>

  • SharePoint 2007 - do it the feature way

    When developing for Wss3 and Microsoft Office SharePoint Server 2007 you don't create your own installers anymore, you build features and solutions. Getting started with this is still a difficult task because there is so much to take into account. The best way to get started are samples, and I just stumbled across a project at CodePlex by the well known SharePoint books writer Scot Hillier with the well chosen name "features". It is packed with feature projects, some donated by the community.

    Another nice sample is from http://sharepointsolutions.com/. I can never find this sample on their site, but I always find it through Google codesearch (http://www.google.com/codesearch). When you search for Feature.xml and SharePoint you find it.. direct link: http://shop.sharepointsolutions.com/shared/SPSolutions.Demo.zip

     

    At Macaw we have our complete own way of building SharePoint Features and Solution files, all within a very automated process that supports both development deployment to keep the development cycle time to a minium, and package deployment that builds our features and solutions files. It is part of our Macaw Solutions Factory. I might write more about this at a later time.

  • SharePoint Security - a dedicated site

    Once upon a time there was just a little bit of information available on SharePoint, and you were happy with all the information you could find. It was the time that Reflector was your best and often only friend to get the details on how thinks were working. Those days are over. It is now completely information overload... although a lot of interesting features of SharePoint are still there to be uncovered because no one knows about them. Documentation is missing, and Reflector is your best friend again. You also see more and more sites that dedicate themselves to just a small part of the SharePoint platform, like sharepointsecurity.com, dedicated to... ah, you can guess.

  • SharePoint 2007 menu item to attach the debugger... cool!

    The SharePoint team provided us with this blog post describing a feature to install in your SharePoint environment that allows you to attach the debugger to the SharePoint process with a click of a button. It becomes available in the site settings menu as shown below:

     

  • SPEventsManager - manage event handlers on your SharePoint 2007 lists

    Gaetan BOUVERET wrote another great tool: a web interface to manage the event handlers on your SharePoint 2007 lists, the SPEventsManager. This project is hosted on CodePlex. The tool is available as a SharePoint Solutions file (.wsp file) that can be easily installed on your SharePoint farm. He announced the new tool in this blogpost. It is a pity his blogposts are in French, not my best language...

    Also checkout his other tool at CodePlex: SharePoint Inspector, in his own words:

    SharePoint Inspector is a free tool to browse your SharePoint 2007 farm. When I talk about SharePoint 2007, I mean Windows SharePoint Services v3 (WSS v3) and Microsoft Office SharePoint Server 2007 (MOSS). Its main purpose is to help SharePoint developer You can see objects composing its structure, get their properties by reflection, which can be very useful when you want to check if your code does what it should do. You can use also some advanced features like activate/deactivate SharePoint features, add/remove event receivers, manage your recycle bin.

  • Ton Stegeman now MOSS 2007 MVP!!

    Ton Stegeman, Dutch SharePoint consultant at e-office, has become MOSS 2007 MVP! He deserves it. I worked together with him on the design of a big MOSS 2007 based intranet in the beta days, and it was a delight to work with him. We had a lot of great brainstorms and discussions, and wrote a lot of design documents together. I hope we will work together again in the future!

    Check out his blog and learn a lot about MOSS 2007!

  • Dundas Chart for SharePoint

    Dundas, long time ASP.NET Data Visualization Control provider, created a SharePoint version of their Chart controls that look impressive. Check out some live SharePoint demo pages. There are versions available for both Wss3 and MOSS2007. The resulting pages are really small, because the charts are either Flash movies or pictures that are loaded asynchronously. In the demo below (online at Dundas) you can interact with the charts because they are rendered as a Flash movie.

    An evaluation version is available for download, I didn't test it out yet, but they promise that it is a full version that will not time out. A watermark will be displayed on rendered images for the evaluation version. Pricing looks also good at less that 2000 US$ for a single server license (no client access licenses).

  • Consistent naming of PowerShell Cmdlets

    PowerShell has some simple guidelines in naming cmdlets so consistence is achieved in cmdlet names.

    Some quotes from this page describing Cmdlet Verb Names:

    Windows PowerShell uses a verb-noun pair format for the names of cmdlets and their derived .NET classes. For example, the Get-Command cmdlet provided by Windows PowerShell is used to retrieve all commands registered in the Windows PowerShell shell. The verb part of the name identifies the action that the cmdlet performs. The noun part of the name identifies the entity on which the action is performed.

    And

    The following list provides guidelines to consider when creating a verb-noun pair:

    • When specifying the verb part of a name, it is strongly recommended to use one of the predefined verb names provided by Windows PowerShell. In doing so, you will ensure consistency between the cmdlets that you create, those provided by Windows PowerShell, and others.

    • To enforce consistency across cmdlets, do not use a synonym of an approved verb name.

    • Use only the present tense of a verb for a name. For example, use "get" instead of "getting".

    • Use a simple, singular noun in cmdlet naming. For example, use "Get-Record" instead of "Get-Records".

    I wish I knew about this convention before writing loads of PowerShell code...

  • youOS, a web operating system. The ultimate AJAX application

    I can't remember how I stumbled across YouOS, but I must say I'm impressed. YouOS is a web operating system running in your browser. It provides a shared virtual server where multiple people can run their applications and interact with eachother. It is a platform to build and host applications that are written in Javascript. The application delivery mechanisms alows you to publish your application to other users running youOS. For storage purposes youOS uses the Amazon S3 storage system. It is still an Alpha release, but it looks very promising.

    The main window of youOS.

    YouOS contains already an extensive application catalog where you can sele4ct the application you would like to run:

    The application catalog.

     

    Although it is possible to run a demo session, you should absolutely create a login account because then you can see some more of the power of youOS. It contains a complete development IDE hosted in your browser.

    You can create our own applications within the youOS Developer Portal.

    Create a new application for youOS. 

    Applications can be authored in the Javascript language in the youOS development IDE which supports versioned code editing. From the ide you can publish your application to the application catalog when you are finished, so all people using youOS can use it.

     

    The application development IDE. Click to enlarge. 

    The IDE provides a high level abstraction layer to author your code. The different hooks where code or information can be added is presentened at the left side of the screen. The actual code that will run in the youOS environment is created after "compilation":

    Actual code generated after compilation.

    As you can see in the code Dojo, an impressive open source javascript toolkit, is used extensively within youOS. YouOS provides a rich API for all kind of functionality. See the online documentation for more information.

    The actual usage of the applications within youOS can be seen on the Developer Scoreboard:

    The developer score card

    The Developer Scorecard.

    It is possible to clone or extend any of the available applications, so the source of all applications is open to everyone. This provides you with real good insight into how to build even complex applications like an editor for youOS.

    If you create a shortcut on your desktop with: "C:\Program Files\Internet Explorer\IEXPLORE.EXE" -k https://www.youos.com you will get an experience that matches a full screen OS (from the youOS blog). Use ALT-F4 to kill the explorer in kiosk mode.

    The weblog of youOS seems a bit dead right now, the last post was of oktober 16 2006.

    Check it out and get inspired!

  • SharePoint Inspector - a cool WSS3/MOSS2007 exploration tool

    I just stumbled accross SharePoint Inspector by Gaetan Bouveret. A great tool that allows you to explore your SharePoint Farm.

    It is a very developer oriented tool that gives you insight in everything that is going on inside SharePoint. Check it out! Even source code available.

    To get the code compiled:

    • Download code
    • Unzip
    • Replace key GatWeb.snk.pfx (password protected) by your own key, name it GatWeb.snk
    • In the current download a file FDisplayView.resx is missing, remove it from the solution (click open FDisplayView.cs)
    • Compile and go!

    Features (quoted from the codeplex site):

    Version 1.0.0.0
    Displays SharePoint objects with reflection on their properties :

    • Farm
    • Servers
    • Services
    • Feature Definitions
    • Solutions
    • Databases
    • Web Applications
    • Site collections
    • Websites
    • Content Types
    • Site Columns
    • Features
    • Lists
    • Associated Workflows
    • Event Receivers
    • Recycle Bin
    • ...
    Actions :
    • Activate / Deactivate feature
    • Add / remove event receiver on list and content type
    • Manage Recycle bin
  • Enumerating projects in a Visual Studio solution

    People writing add-ins for Visual studio probably have come across the nightmare of the Visual studio object model to go through the projects within a solution. I had to get the list of projects in a solution, and for each solution its output path in the current configuration. Although I need the code in C# later on, the best way to check out how to program against the Visual Studio object model is within the Macro IDE of Visual Studio (Tools->Macros->Macros IDE).

    Although the question seems quite straightforward, the trouble begins when you have Solution Folders containing projects. The Solution object has a property called Projects, but Solution Folders are also seen as Projects. A project has project items. A project item can be a folder, a file, or... a project. You have to see it to believe the mess.

    After a lot of trial and error I got to a solution where I check if a project item has its ConfigurationManager property set, if this is the case, it must be a project. Not sure if this is the best approach, but it works for me. For example for the following project structure using Solution Folders:

    I get the following output:

    And the code to accomplish this (paste in  Macros IDE):

    Sub SolutionProjects()
            Dim project As EnvDTE.Project
            Write("--------- DUMP OF ALL PROJECTS IN CURRENT SOLUTION -------------")
            Try
                If Not DTE.Solution.IsOpen Then
                    Write("There is no solution open.")
                Else
                    For Each project In DTE.Solution.Projects
                        NavProj(project)
                    Next
                End If
            Catch ex As System.Exception
                Write(ex.ToString)
            End Try
        End Sub
        Sub NavProj(ByVal proj As Project)
            Dim outputPathProperty As EnvDTE.Property
            Dim outputPath As String
    

    If Not (proj.ConfigurationManager Is Nothing) Then ' It's a project! outputPathProperty = _ proj.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath") If outputPathProperty Is Nothing Then outputPath = "<no output path set>" Else outputPath = outputPathProperty.Value End If Write("### Project: " + proj.Name + ", OutputPath: " + outputPath) Else NavProjItems(proj.ProjectItems) End If End Sub Sub NavProjItems(ByVal projItems As ProjectItems) Dim projectItem As EnvDTE.ProjectItem

        <span style="color: rgb(0,0,255)">If</span> <span style="color: rgb(0,0,255)">Not</span> (projItems <span style="color: rgb(0,0,255)">Is</span> <span style="color: rgb(0,0,255)">Nothing</span>) <span style="color: rgb(0,0,255)">Then
    

    For Each projectItem In projItems If Not (projectItem.SubProject Is Nothing) Then ' Recurse, can be an Enterprise project in ' Visual Studio .NET 2002/2003 or a solution folder in VS 2005 NavProj(projectItem.SubProject) End If Next End If End Sub

    Sub Write(ByVal s As String) Dim out As OutputWindowPane = GetOutputWindowPane("MACRO OUTPUT", True) out.OutputString(s) out.OutputString(vbCrLf) End Sub
    Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput) If show Then win.Visible = True Dim ow As OutputWindow = win.Object Dim owpane As OutputWindowPane Try owpane = ow.OutputWindowPanes.Item(Name) Catch e As System.Exception owpane = ow.OutputWindowPanes.Add(Name) End Try owpane.Activate() Return owpane End Function

  • VS 2005 image library - all the icons you need !

    I am busy writing a toolwindow extension for Visual Studio 2005, and I needed some icons for my toolbar in the same style as Visual Stuido 2005. In search of this I stumbled accross the VS2005ImageLibrary, a zip file containing all the icons you need!

    Path: X:\Program Files\Microsoft Visual Studio 8\Common7\VS2005ImageLibrary

  • PowerShell - Windows PowerShell In Action - Bruce Payette

    I have done a lot of coding in Windows PowerShell last months, and my biggest help next to some of the great weblogs on PowerShell like the weblog of The PowerShell Guy and the PowerShell team., was an early access version of the Windows PowerShell in Action e-book. Today I got the final e-book version, and it got even better! You can now preorder the book at Amazon, it will be available real soon. If you are serious about PowerShell: get this book!! It will get 5-* ratings on Amazon, I'm sure!

  • PowerShell - function return values implementing IEnumerable are decomposed into an array

    In this blog post I wrote about (by me) unexpected implicit type conversion on return values of functions which is actually really cool: all types returned that implement the IEnumerable interface are decomposed in an array of the elements that are enumerated in the IEnumerable type. This collection of elements is returned "on the pipeline". This decompositioning goes one level deep (a pipeline is linear). So if an array of values is returned, the values don't get decomposed. An array with a single element can be returned as follows: ,$element.

    An example follows below with two functions: foo where the return value gets decomposed into an array, and bar where we stoped the decompositioning by returning the element in an array:

    function foo
    {
        $arraylist = new-Object System.Collections.ArrayList
        [void]$arraylist.Add("one")
        [void]$arraylist.Add("two")
        [void]$arraylist.Add("three")
        return $arraylist # implicit conversion to array
    }

    function bar
    {
        $arraylist = new-Object System.Collections.ArrayList
        [void]$arraylist.Add("one")
        [void]$arraylist.Add("two")
        [void]$arraylist.Add("three")
        return ,$arraylist
    }

    foo | foreach ($_) {Write-Host "foo value (with type: $($_.GetType()) in pipe: $_" }
    bar | foreach ($_) {Write-Host "bar value (with type: $($_.GetType()) in pipe: $_" }

    This results in:

    foo value (with type: System.String in pipe: one
    foo value (with type: System.String in pipe: two
    foo value (with type: System.String in pipe: three
    bar value (with type: System.Collections.ArrayList in pipe: one two three

  • PowerShell - referencing files relative to the currently executing script

    I often have the situation that that I want to do a relative reference  to a script file from another script file. This works ok if we execute the referencing script file from its current location, but what if  that script is referenced as well. Ok, a bit vague, an example:

    Folder c:\test contains script X.ps1
    Folder c:\test\sub contains script Y.ps1
    Folder c:\test\sub contains script Z.ps1

    The initially executing script is: C:\test\X.ps1

    The scripts are defined as follows:

    C:\test\X.ps1:
    ./sub/Y.ps1
    Write-Host "X"

    C:\test\sub\Y.ps1:
    ./Z.ps1 # this one not found, because the current folder is c:\test, not c:\test\sub
    Write-Host "Y"

    C:\test\sub\Z.ps1:
    Write-Host "Z"

    I have this problem if Y.ps1 and Z.ps1 are part of a utility library, and X.ps1 is one of the calling scripts. A good example is the psexpect library from www.codeplex.com where I had exactly this problem.

    The PowerShell guy (/\/\o\/\/) came to the rescue with the following solution:

    Split-Path -Path $MyInvocation.MyCommand.Path -Parent

    We can rewrite our scripts as follows:


    C:\test\X.ps1:
    $executingScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
    Write-Host "Script X: script folder=$executingScriptDirectory"
    & "$executingScriptDirectory/sub/Y.ps1"
    Write-Host "X"

    C:\test\sub\Y.ps1:
    $executingScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
    Write-Host "Script Y: script folder=$executingScriptDirectory"
    & "$executingScriptDirectory/Z.ps1"
    Write-Host "Y"

    C:\test\sub\Z.ps1:
    Write-Host "Z"

    • The start script C:\test\X.ps1 can now be executed from any location.
    • The library script C:\test\sub\Y.ps1 can be utilized by any script.

    Note that this code must be executed in the body of the script, and not from within a function!!

    The one strange thing that puzzles me now is why PowerShell Analyzer gives the following exception:

    --------------------------------------------------------------------------------
    POWERSHELL EXCEPTION
    EXCEPTION TYPE:System.Management.Automation.CmdletInvocationException
    MESSAGE:Cannot find drive. A drive with name '$executingScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
    Write-Host "Script X' does not exist.
    POSITION:
    At line:1 char:39
    + $executingScriptDirectory = Split-Path <<<< -Path $MyInvocation.MyCommand.Definition -Parent
    --------------------------------------------------------------------------------

    So many words to explain a problem and solve an issue that was so easy in cmd.exe, ~dp0 did the job!

  • PowerShell - Strange implicit type conversion

    PowerShell is great, but sometimes it has some strange quircks that can cost you a lot of time to solve. My latest "obstacle" was the following situation:

    function ArgsToArrayList {
      $al = new-object System.Collections.ArrayList
      $args | foreach { [void] $al.add($_) }
      $al
    }

    $x = ArgsToArrayList 1 2 3 4 5
    write-Host "5 entries, type: " $x.GetType()
    $x = ArgsToArrayList
    write-Host "0 entries, is null: " ($x -eq $null)

    I expect the function ArgsToArrayList to always return an object of type System.Collections.ArrayList, independent of the number of arguments passed. I was wrong.

    PowerShell converts the return value of the function ArgsToArrayList from System.Collections.ArrayList to System.Object[] when it contains entries, and to $null when the arraylist is empty.

    So the output of the above code is:

    5 entries, type: System.Object[]
    0 entries, is null: True

    Beats me...

  • VS.NET 2005 Tool Window for testing XPath expressions - XPathmania

    I had to define some XPath expressions to query information from an XML document. I couldn't find any standard support for this in Visual Studio 2005, but after some searching I stumbled accross XPathmania, a tool window developed by Don Xml. Works like a breeze! See below. See this blog entry for more information. Download it here. Source code is available as well.

  • Console2 - a great Windows console window enhancer for cmd.exe and PowerShell

    Through a discussion thread on the PowerShell Community Extensions forum at Codeplex I found Console2, a great tool that enhances the working experience with Windos console window that is normally used by Cmd.exe and PowerShell. You can resize the window dynamically, do normal text selections (use shift+mouse), have tabs, and do all kind of style configurations.See the discussion thread for information on configuration for PowerShell. Check it out!