Shawn Cicoria - CedarLogic

Perspectives and Observations on Technology

Recent Posts

Sponsors

Tags

General





Community

Email Notifications

Blogs I Read

Archives

Other

Use OpenDNS

Issues with OneDrive for business and Document Cache–Don’t mix C2R and MSI installs

With the latest updates to Office, an issue that rears it’s ugly head if you’ve mixed both C2R and MSI installs of any Office product (2013).  That means Office, Visio, Project, SharePoint designer, and OneDrive for Business Sync Client.

 

If you get into this mess, try to uninstall all the C2R or MSI – then get them all consistent;

 

#1 – can’t mix click-to-run and MSI installs on the same machine:

If any are mixed, you need to uninstall.

To start fresh:

1. Run http://support.microsoft.com/kb/2739501

a. Both MSI then C2R

2. Run ROIScan to ensure nothing is left:

a. http://gallery.technet.microsoft.com/office/68b80aba-130d-4ad4-aa45-832b1ee49602

3. Once you’re all clean:

a. C2R

i. Use the https://portal.office.com/OLS/MySoftware.aspx

ii. SharePoint designer is under “Tools”

iii. Visio is there if your org has a license..

b. MSI

i. Get them all in FULL downloads from MSDN, or wherever you obtain your installs from

# for internal, step #1 – in toolbox there is OffScrub

SharePoint 2013 Farm in Less than an Hour–New Azure Portal and Azure Templates

Soon, you’ll be able to author your own templates, but as of today, you can provision an 3 Machine SharePoint 2013 Farm – have it running in less than 1 hour with just a few clicks.

For details take a look here:

SharePoint Server Farm at http://azure.microsoft.com/en-us/documentation/articles/virtual-machines-sharepoint-farm-azure-preview/
SharePoint Server Farm Configuration Details at http://azure.microsoft.com/en-us/documentation/articles/virtual-machines-sharepoint-farm-config-azure-preview/

Now, for some fun…

First, navigate to the new portal at http://portal.azure.com

Once there, choose “New”.

There you’ll get the new experience for Template based provisioning.  Click on “Show Everything” to see the full Gallery of Microsoft and non-Microsoft templates.

image

After choosing a SP Farm, you set a few global settings, or you can choose to modify the template choices, like Machine size (A5 vs. A4, etc.).  Even account names, etc.

I chose the easy route.

image

 

After a bit, and if you chose to “Add to Start Board” you’ll see your farm provisioning notifications, and eventually your finished Farm Tile.

image

 

image

The following shows the individual VM status (I shut mine down to save some $).  But easy enough to restart when I need it.

Remember, that while it’s COLD you only pay for the actual non-zero’s bits in the Page Blobs for the VHD storage. So, a 60 GB disk really only may be using 5 GB etc.

image

Posted: 07-14-2014 6:31 AM by cicorias | with no comments
Filed under: ,
Disabling HyperV on Surface Pro 3 So Connected Standby will work or not work–depending on your mood

If you’re received your SP3 and you enabled HyperV you may have noticed that Connected Standby (new to x64) will then be disabled.

You’ll get this is you install Visual Studio 2013 with the Windows Phone emulator support in VS2013.

First step is to give you an option to “boot” or “restart” Windows in a mode with HyperV on or off so connected standby will “not work” or “work” (opposite of HyperV setting").

Set HyperV as Default

C:\WINDOWS\system32>Bcdedit /copy {default} /d "HyperVisor Off"
The entry was successfully copied to {22393409-9568-11e2-be59-3c970e7cc5fa}.

C:\WINDOWS\system32>bcdedit /set {22393409-9568-11e2-be59-3c970e7cc5fa} hypervisorlaunchtype off
The operation completed successfully.

Courtesy of Scott Hanselman – an easy UI way to restart your machine in your Choice.

http://www.hanselman.com/blog/SwitchEasilyBetweenVirtualBoxAndHyperVWithABCDEditBootEntryInWindows81.aspx

In order to access the new boot menu, I select Settings (Windows Key + C) then Power, and Restart but hold down shift on the keyboard while clicking Restart with the mouse.

Note that the “Other Operating System” will be the one that just got copied.

Comparing Hash of downloaded Files with PowerShell

I can’t claim 99% of this – main credit to : http://www.tinyint.com/index.php/2011/09/14/get-an-md5-or-sha1-checksum-with-powershell/

Param (
        [string]$File=$(throw("You must specify a filename to get the checksum of.")),
        [string]$ProvidedHash,
        [ValidateSet("sha1","md5")]
        [string]$Algorithm=("sha1")
        
)

function Get-Checksum
{
    Param (
        [string]$File=$(throw("You must specify a filename to get the checksum of.")),
        [ValidateSet("sha1","md5")]
        [string]$Algorithm=("sha1")
        
    )

    $fs = new-object System.IO.FileStream $File, “Open”, “Read”, “Read”;
    $algo = [type]"System.Security.Cryptography.$Algorithm"
	$crypto = $algo::Create()
    $hash = [BitConverter]::ToString($crypto.ComputeHash($fs)).Replace("-", "")
    $fs.Close()
    return $hash
}

$calchash = Get-Checksum $File $Algorithm $ProvidedHash

if ( $calchash -eq $ProvidedHash ) {
    Write-Host "hash match" -ForegroundColor Green;
}
else {
    Write-Host "hash doesn't match" -ForegroundColor Red
    write-host "Provided:" $ProvidedHash "Calculated: " $calchash
}
WOPI Host Sample has been updated…

The solution and project have been updated to MVC5, and Web API 2.  In addition, editing PowerPoint (PPTX), and Excel files has been added.  Word Editing is not part of the solution. Also, PDF viewing is enabled.

The latest Solution and information is up on Code.MSDN:

http://code.msdn.microsoft.com/Building-an-Office-Web-f98650d6

And also here: http://cicoria.com/downloads/CL-OwaWopiNetFx45MVC520140131.zip 

The old post is here:

http://cicoria.com/cs1/blogs/cedarlogic/archive/2013/07/22/building-an-office-web-apps-owa-wopi-host.aspx

Fiddler and Direct Access

Fiddler puts some stuff in the registry that breaks Direct Access.

The following will cleanup after Fiddler runs

reg delete HKLM\SYSTEM\CurrentControlSet\Services\iphlpsvc\Parameters\ProxyMgr /va /f

Updating email address for SharePoint online users if they’re a Live / Microsoft Account…

If you have a SharePoint online ()365) site, and you invite users that logon with a “Microsoft Account”, those users won’t be able to receive email.  Things such as alerts won’t work.

However, you can run the code below and it will parse out all users that are “invitees” and part of the Microsoft account structure (Live.com) and just update their email, based upon what their Microsoft Account email address is.

Note: use this at your own risk.  This makes use of logon via Forms/Claims that is part of the solution here:

Remote Authentication in SharePoint Online Using the Client Object Model

http://code.msdn.microsoft.com/Remote-Authentication-in-b7b6f43c

Full solution is here: Solution

namespace ConsoleApplication1
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            if (args.Length < 1) { Console.WriteLine("SP_Ctx <url>"); return; }
            string targetSite = args[0];
            using (ClientContext ctx = ClaimClientContext.GetAuthenticatedContext(targetSite))
            {
                if (ctx != null)
                {
                    ctx.Load(ctx.Web,
                        website => website.SiteUsers,
                        website => website.SiteUserInfoList); // Query for Web

                    ctx.ExecuteQuery(); // Execute
                    ListSiteUsers(ctx);
                }
            }
            Console.WriteLine("Press enter to exit...");
            Console.ReadLine();
        }

        static void ListSiteUsers(ClientContext ctx)
        {
            var users = ctx.Web.SiteUsers.AsQueryable();

            foreach (var user in users)
            {
                ctx.Load(user, u => u.UserId);
                ctx.ExecuteQuery();
                if (user.UserId == null)
                {
                    string[] parts = user.LoginName.Split('|');
                    if (parts.Length == 3 && parts[1].Equals("membership", StringComparison.InvariantCultureIgnoreCase))
                        UpdateUser(ctx, user, parts[2]);
                }

            }
        }

        static void UpdateUser(ClientContext ctx, User user, string liveId)
        {
            string[] parts = liveId.Split('#');

            var email = parts[1];

            Console.WriteLine("user: {0}  email: {1}", user.LoginName, email);
            var userToUpdate = ctx.Web.SiteUsers.GetByLoginName(user.LoginName);
            user.Context.ExecuteQuery();
            if (null != userToUpdate)
            {
                userToUpdate.Email = email;
                userToUpdate.Update();
                ctx.ExecuteQuery();
            }
            else
                Console.WriteLine("User was null: {0}", user.LoginName);
        }

    }
}
Why it doesn’t take an army to build a usable web site…

We should hopefully learn a lesson from how http://healthcare.gov was build vs. http://www.thehealthsherpa.com/

http://www.ihealthbeat.org/articles/2013/11/12/sf-programmers-build-bare-bones-federal-exchange-site-alternative

For too long, the idea of throwing commodity developers and large quantities of them at a problem has some believing that you can achieve good quality and results faster and better. Far from the truth. Building software is still a craft. It takes commitment, experience, and trial and error. And lots of practice.

Running ASP.NET admin site from command line

Great tip from Dominic Baer.

 

http://leastprivilege.com/2012/06/28/managing-asp-net-membership-and-roles-without-visual-studio/

 

 

 

& ‘C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.EXE’ /path:”C:\Windows\
Microsoft.NET\Framework64\v4.0.30319\ASP.NETWebAdminFiles” /port:8080 /vpath:”/asp.netwebadminfiles”

Afterwards you can navigate to the site using this URL:

http://localhost:8080/asp.netwebadminfiles/default.aspx?applicationPhysicalPath=path&applicationUrl=/vdir

Host named site collections and Web Application Extensions

The question came up about whether the mix of an SharePoint 2013 extended web application that may have different authentication providers, could also support Host Named Site Collections (HNSC).

Well, they can.  The documentation isn’t that clear, never seen it explicitly called out.

But, just from a foundation of setting up a web application, extending it, then establishing a HNSC that is addressable from 2 different SP Zones (Extended zone), these are the simple steps:

 

#1
New-SPWebApplication -Name 'Wingtip Public HNSC' -port 8000 -ApplicationPool WingtipHnscAppPool -ApplicationPoolAccount (Get-SPManagedAccount 'wingtip\svc_spcontent') -AuthenticationProvider (New-SPAuthenticationProvider –UseWindowsIntegratedAuthentication)

#1.1 - create a root site collection....
New-SPSite 'http://WINGTIPSERVER:8000' -Name 'Portal' -Description 'Portal on root' -OwnerAlias 'wingtip\administrator' -language 1033 -Template 'STS#0'

#2
Get-SPWebApplication 'http://WINGTIPSERVER:8000' | New-SPWebApplicationExtension -Name "Internet Site" -Zone "Internet" -Port 80 -URL "http://internet.wingtip.com"

#3
New-SPSite 'http://hnsc1.wingtip.com:8000' -HostHeaderWebApplication 'http://WINGTIPSERVER:8000’ -Name 'HNSC1' -Description 'HNSC 1' -OwnerAlias 'wingtip\administrator' -language 1033 -Template 'STS#0'

#4
Set-SPSiteUrl (Get-SPSite 'http://hnsc1.wingtip.com:8000') –Url 'http://p-hnsc1.wingtip.com' –Zone Internet

Building an Office Web Apps (OWA) WOPI Host

UPDATE: January 31, 2014

The solution and project have been updated to MVC5, and Web API 2.  In addition, editing PowerPoint (PPTX), and Excel files has been added.  Word Editing is not part of the solution. Also, PDF viewing is enabled.  See the updated post here:

http://cicoria.com/cs1/blogs/cedarlogic/archive/2014/01/31/wopi-host-sample-has-been-updated.aspx

//end

The latest version of OWA in an on-premises deployment decouples the dependency on SharePoint. For those organizations that perhaps have invested somewhat in non-SharePoint content or document management systems, this offers an opportunity to provide the OWA experience with content from your site.

Get the solution zip

WOPI Host

The WOPI host protocol is defined at this location: http://msdn.microsoft.com/en-us/library/hh643135(v=office.12).aspx

There’s a great overview, introducing WOPI in a blog post from the Office development team here: http://blogs.msdn.com/b/officedevdocs/archive/2013/03/21/introducing-wopi.aspx

In addition, a good overview of the architecture in 2013 (vs. 2010) is shown here:

http://technet.microsoft.com/en-us/library/jj219437.aspx

Callback interface

Note that a WOPI host has to respond to a direct call from OWA for the content. That is illustrated in the above post with this sequence diagram:

image

 

Building WOPI Host

So, for this post, we’re going to cover a working WOPI host that will utilize OWA for display content (Word, Excel, and PowerPoint) with an OWA on-premises deployment.

Primary Interfaces

To get started, the bare minimum implementation, for viewing, requires 2 interfaces implemented as REST endpoints on your WOPI Host.

The solution contains a series of API controllers. The FilesController implements the 2 prmiamry interfaces – the first is a GET which returns the file information; the second returns the content as a stream.

Files

API

Description

GET api/wopi/files/{name}?access_token={access_token}

Required for WOPI interface - on initial view

GET api/wopi/files/{name}/contents?access_token={access_token}

Required for View WOPI interface - returns stream of document.

 

Discovery XML

Within the ~/App_Data location, there’s a discovery.xml file. This is retrieved using the following URL from the OWA server. That XML just needs to be saved to the location.

http://owa1.wingtip.com/hosting/discovery

The solution builds the proper full URL based upon the file type, by examining this file.

Uploading Files / Link Generation

For the sake of testing, you can upload files using the Upload API. This will accept multiple files and return a JSON result that is a collection of Links, with access tokens for each file.

The Link generation is used to generate a fully qualified link that can be used to view an Office file on OWA which will be consumed from the WOPI host.

Access Token

OWA supports the WOPI host use of an access token. Note that the sample provides a HMACSHA256 of the file name using a random generated salt value.

Deployment

Note that the WOPI host MUST be HTTP addressable from the OWA server. In this sample, you also have to turn off HTTPS. Check the OWA TechNet articles on how.

Source Code:

The solution file is here…

Here’s the GetInfo portion

        /// <summary>
        /// Required for WOPI interface - on initial view
        /// </summary>
        /// <param name="name">file name</param>
        /// <param name="access_token">token that WOPI server will know</param>
        /// <returns></returns>
        public CheckFileInfo Get(string name, string access_token)
        {
            Validate(name, access_token);

            var fileInfo = _fileHelper.GetFileInfo(name);
            return fileInfo;
        }

 

And the Contents portion

 /// <summary>
 /// Required for View WOPI interface - returns stream of document.
 /// </summary>
 /// <param name="name">file name</param>
 /// <param name="access_token">token that WOPI server will know</param>
 /// <returns></returns>
 public HttpResponseMessage GetFile(string name, string access_token)
 {
     try
     {
         Validate(name, access_token);
         var file = HostingEnvironment.MapPath("~/App_Data/" + name);
         var rv = new HttpResponseMessage(HttpStatusCode.OK);
         var stream = new FileStream(file, FileMode.Open, FileAccess.Read);

         rv.Content = new StreamContent(stream);
         rv.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
         return rv;

     }
     catch (Exception ex)
     {
         var rv = new HttpResponseMessage(HttpStatusCode.InternalServerError);
         var stream = new MemoryStream(UTF8Encoding.Default.GetBytes(ex.Message ?? ""));
         rv.Content = new StreamContent(stream);
         return rv;
     }
 }

 

And, KeyGen – which generates the hash values

namespace MainWeb.Helpers
{
    public interface IKeyGen
    {
        string GetHash(string value);

        bool Validate(string name, string access_token);
    }
    public class KeyGen : IKeyGen
    {
        byte[] _key;
        int _saltLength = 8;

        static RNGCryptoServiceProvider s_rngCsp = new RNGCryptoServiceProvider();

        public KeyGen()
        {
            var key = WebConfigurationManager.AppSettings["appHmacKey"];
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("must supply a HmacKey - check config");
            _key = Encoding.UTF8.GetBytes(key);
        }

        public string GetHash(string value)
        {
            byte[] salt = new byte[_saltLength];
            s_rngCsp.GetBytes(salt);

            var saltStr = Convert.ToBase64String(salt);
            return GetHash(value, saltStr);
        }

        private string GetHash(string value, string saltStr)
        {
            //Not really secure; must use random salt to ensure non-repeat....
            HMACSHA256 hmac = new HMACSHA256(_key);
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(saltStr + value));
            var rv = Convert.ToBase64String(hash);
            return saltStr + rv;
        }


        public bool Validate(string name, string access_token)
        {
            var targetHash = GetHash(name, access_token.Substring(0,_saltLength + 4));  //hack for base64 form
            return String.Equals(access_token, targetHash);
        }


    }
}

 

File Helper

public interface IFileHelper
{
    CheckFileInfo GetFileInfo(string name);
}

public class FileHelper : IFileHelper
{
    public CheckFileInfo GetFileInfo(string name)
    {
        var fileName = GetFileName(name);
        FileInfo info = new FileInfo(fileName);
        string sha256 = "";

        using (FileStream stream = File.OpenRead(fileName))
        using (var sha = SHA256.Create())
        {
            byte[] checksum = sha.ComputeHash(stream);
            sha256 = Convert.ToBase64String(checksum);
        }

        var rv = new CheckFileInfo
        {
            BaseFileName = info.Name,
            OwnerId = "admin",
            Size = info.Length,
            SHA256 = sha256,
            Version = info.LastWriteTimeUtc.ToString("s")
        };

        return rv;
    }


    internal string GetFileName(string name)
    {
        var file = HostingEnvironment.MapPath("~/App_Data/" + name);
        return file;
    }
}

Finally, for this Post a WOPI helper class

public class WopiAppHelper
{
    string _discoveryFile;
    WopiHost.wopidiscovery _wopiDiscovery;

    public WopiAppHelper(string discoveryXml)
    {
        _discoveryFile = discoveryXml;

        using (StreamReader file = new StreamReader(discoveryXml))
        {
            XmlSerializer reader = new XmlSerializer(typeof(WopiHost.wopidiscovery));
            var wopiDiscovery = reader.Deserialize(file) as WopiHost.wopidiscovery;
            _wopiDiscovery = wopiDiscovery;
        }
    }


    public WopiHost.wopidiscoveryNetzoneApp GetZone(string AppName)
    {
        var rv = _wopiDiscovery.netzone.app.Where(c => c.name == AppName).FirstOrDefault();
        return rv;
    }

    public string  GetDocumentLink(string wopiHostandFile)
    {
        var fileName = wopiHostandFile.Substring(wopiHostandFile.LastIndexOf('/') + 1);
        var accessToken = GetToken(fileName);
        var fileExt = fileName.Substring(fileName.LastIndexOf('.') + 1);
        var tt = _wopiDiscovery.netzone.app.AsEnumerable().Where(c => c.action.Where(d => d.ext == fileExt).Count() > 0);

        var appName = tt.FirstOrDefault();

        if (null == appName) throw new ArgumentException("invalid file extension " + fileExt);

        var rv = GetDocumentLink(appName.name, fileExt, wopiHostandFile, accessToken);

        return rv;
    }

    string GetToken(string fileName)
    {
        KeyGen keyGen = new KeyGen();
        var rv = keyGen.GetHash(fileName);

        return HttpUtility.UrlEncode(rv);
    }

    const string s_WopiHostFormat = "{0}?WOPISrc={1}&access_token={2}";
    public string GetDocumentLink(string appName, string fileExtension, string wopiHostAndFile, string accessToken)
    {
        var wopiHostUrlsafe = HttpUtility.UrlEncode(wopiHostAndFile.Replace(" ", "%20"));
        var appStuff = _wopiDiscovery.netzone.app.Where(c => c.name == appName).FirstOrDefault();

        if (null == appStuff)
            throw new ApplicationException("Can't locate App: " + appName);


        var appAction = appStuff.action.Where(c => c.ext == fileExtension).FirstOrDefault();
                    if (null == appAction)
            throw new ApplicationException("Can't locate UrlSrc for : " + appName);

        var endPoint = appAction.urlsrc.IndexOf('?');
        var fullPath = string.Format(s_WopiHostFormat, appAction.urlsrc.Substring(0, endPoint), wopiHostUrlsafe, accessToken); 

        return fullPath;
    }
}
Planning Poker Win8 App.

Check out an in process App for Win 8 that makes use of TFS OData for planning poker

http://www.teamplanningpoker.com/HowTo/Win8/CreateYourFirstPlanningPokerSession

About:

Team Planning Poker was created by Mike Douglas and Deliveron Consulting Services to help distributed and co-located teams effeciently point your projects' backlogs that are using Team Foundation Server or Team Foundation Service.

Deliveron is a technology consulting company focused on delivering end-to-end solutions for clients. We have expertise in custom application development, system integration using BizTalk Server, enterprise portals and workflow with SharePoint, and data management and business intelligence using SQL Server.

Team Foundation Server and Team Foundation Service are part of Visual Studio ALM tools that help improve the effeciency and quality of development. Features includ Project Management, Requirements Management, Development, Test Case Management, Build Automation. There are several ways to start using TFS with little or no additional cost. Sign up with Team Foundation Service to get started.

Office Web Apps–WOPI Host and url paths

If you’re following along with the post on creating a WOPI host, it’s never fully apparent that you MUST adhere to the path shown in the article here:

http://blogs.msdn.com/b/officedevdocs/archive/2013/03/20/introducing-wopi.aspx

That is, the path to your host must contain ‘/wopi/files’.  It wasn’t clear to me in that article, nor could I find it in the WOPI spec. http://msdn.microsoft.com/en-us/library/hh622722(v=office.12).aspx

So, for example, here are some Routes I used in MVC

 

            config.Routes.MapHttpRoute(
                name: "Contents",
                routeTemplate: "api/wopi/files/{name}/contents",
                defaults: new { controller = "files", action = "GetFile" }
                );

            config.Routes.MapHttpRoute(
                name: "FileInfo",
                routeTemplate: "api/wopi/files/{name}",
                defaults: new { controller = "Files", action = "Get" }
                );

 

 

Here are the Actions

public class FilesController : ApiController
    {

        IFileHelper _fileHelper;
        public FilesController() : this(new FileHelper())
        {

        }

        public FilesController(IFileHelper fileHelper)
        {
            _fileHelper = fileHelper;
        }


        /// <summary>
        /// Required for WOPI interface - on initial view
        /// </summary>
        /// <param name="name"></param>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public CheckFileInfo Get(string name, string access_token)
        {
            var fileInfo = _fileHelper.GetFileInfo(name);
            return fileInfo;
        }


        /// <summary>
        /// Required for View WOPI interface - returns stream of document.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public HttpResponseMessage GetFile(string name, string access_token)
        {
            try
            {
                var file = HostingEnvironment.MapPath("~/App_Data/" + name);
                var rv = new HttpResponseMessage(HttpStatusCode.OK);
                var stream = new FileStream(file, FileMode.Open, FileAccess.Read);

                rv.Content = new StreamContent(stream);
                rv.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                return rv;

            }
            catch (Exception ex)
            {
                var rv = new HttpResponseMessage(HttpStatusCode.InternalServerError);
                var stream = new MemoryStream(UTF8Encoding.Default.GetBytes(ex.Message ?? ""));
                rv.Content = new StreamContent(stream);
                return rv;
            }
        }





    }

 

And here is the helper

 

    public interface IFileHelper
    {
        CheckFileInfo GetFileInfo(string name);
    }

    public class FileHelper : IFileHelper
    {
        public CheckFileInfo GetFileInfo(string name)
        {
            var fileName = GetFileName(name);
            FileInfo info = new FileInfo(fileName);
            string sha256 = "";

            using (FileStream stream = File.OpenRead(fileName))
            using (var sha = SHA256.Create())
            {
                byte[] checksum = sha.ComputeHash(stream);
                sha256 = Convert.ToBase64String(checksum);
            }

            var rv = new CheckFileInfo
            {
                BaseFileName = info.Name,
                OwnerId = "admin",
                Size = (int)info.Length,
                SHA256 = sha256,
                Version = DateTime.Now.ToString("s")
            };

            return rv;
        }


        internal string GetFileName(string name)
        {
            var file = HostingEnvironment.MapPath("~/App_Data/" + name);
            return file;
        }
    }
Note to self–SQL Alias on x64–you need to set both 32/64 cliconfg.exe
1. Start “C:\windows\system32\cliconfg.exe”
2. Start “C:\windows\syswow64\cliconfg.exe”
Office 365 SharePoint and PDF files…

Recently, O365 added some server side rendering of PDF files.  Problem is if you have PDF files and an anonymous site, if a user clicks the PDF link, it will then try to authenticate that users.  Which defeats the purpose of anonymous.

You’ll need to change the links as follows:

Append either to the following (1st opens in the server side PDF reader; 2nd downloads to the client to read.

?Web=1

?Web=0

to the end of the URL.

More Posts Next page »