• Will Buffington's WebLog

    ‘Document not saved’ or file sharing error saving an Excel file? Maybe your desktop is too cluttered.

    • 4 Comments

    Sometimes there’s a problem with saving Excel files on Windows 7 machines in the enterprise. If you haven’t seen this problem yet, count yourself fortunate. The problem is, there are a couple of different flavors of this problem and both are frustrating. I’m  talking about what happens when you try to save an Excel 2007 or 2010 document when you’re working on a Windows 7 machine. You may get an error indicating the document wasn’t saved or that someone else is using the file and can’t be saved. Let’s break this problem down intoimage several yummy flavors:

    “Document not saved” – When this one happens, the error is consistent. This is a problem that can happen when you try to save to a location on your machine that is redirected to a network location, like your desktop. The issue won’t happen if you save to a local directory on the machine. Even more bizarre, the problem only affects Excel – not Word or PowerPoint. Only Excel. Upon closer examination, a debug revealed the server was throwing a “Quota_Exceeded” error back at Excel and denying the save. But this can happen even when quotas aren’t enabled on the server. Say WHAT? Yep, it’s true. While quotas may be the cause of the problem in some cases, this can affect a server that specifically has no quotas set. If your server is Small Business Server you will want to check quotas as they are set by default. You have to actually go in and disable them for quotas not to be enabled out of the box. But let’s assume quotas aren’t the problem. Take a look at the size of your desktop folder on the server. A folder that measures in gigabytes should send up red flags for obvious reasons. For one, Windows has to load that big folder before it can display your desktop on startup. And if it has to slog through gigabytes of information then the startup time is going to be slow. It’s recommended that you get rid of the unnecessary items from the desktop by moving them elsewhere or by deleting them. This problem has been confirmed on a desktop running over 6GB in files.

    “Document not saved” – Yet another flavor of the ‘document not saved’ error. In this particular case, the error happens when some of the following conditions are true:

    • You have a large file shared on a network by several users;
    • the file may disappear leaving only a file in the temp file with a hexadecimal name (this is the lock file) ;
    • neither the temp file or the original file are left in the save directory

    This ‘document not saved’ problem happens when two or more people save changes to the Excel file at the same time. The only known workaround for this problem is an add-in which prevents saving the document at the same time. In order to acquire the add-in, which isn’t approved for release as yet, contact Microsoft Support.

    “Your changes could not be saved to <Document Name> because of a sharing violation. Try saving to a different file” – This problem appears to happen sporadically when it manifests. This one may also be followed by the following errors: “The file you are trying to open, <Random Characters>, is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Do you want to open the file now?" This problem can occur if you repeatedly save the workbook at short intervals. For this problem, there is a fix available in Microsoft Knowledge Base article 982125 (http://support.microsoft.com/kb/982125).

    Failure to save files from Windows 7 or Windows Server 2008 R2 clients – This particular version of the file save problem is covered under Microsoft KB Article 234932 (http://support.microsoft.com/kb/2434932) and includes a hotfix. This problem only affects clients running Windows 7 or Windows 2008 R2 when you map a share to a server, make the share an offline location and then save files to that share.

    In this problem, the temporary files that get created aren’t synchronizing correctly to the server share. What’s worse, the original files on the share are deleted and replaced with damaged TMP files. You don’t even receive a notification that the files were deleted, though you will receive a conflict notification that the files are missing from the server after you restart the server. This problem doesn’t affect files saved on the local machine.

  • Will Buffington's WebLog

    “Excel cannot insert the sheets into the destination workbook, because it contains fewer rows and columns…”

    • 13 Comments

    When you receive this error in Microsoft Excel, it would seem to be pretty self explanatory.

    Excel cannot insert the sheets into the destination workbook, because it contains fewer rows and columns than the source workbook. To move or copy the data to the destination workbook, you can select the data, and then use Copy and Paste commands to insert it into the sheets of another workbook.

    Excel 2003 and earlier spreadsheets (XLS file extension) has a max of 65,536 rows and 256 columns. With Excel 2007 and 2010 you now have the metro file format (XLSX, XLSM, etc.) which is capable of handling 1,048,576 rows and 16,384 columns of data. This error appears when you try to copy or move a metro image file sheet to a non-metro (XLS) sheet. Basically you’re trying to fit a much larger page into a small book and still expect the sizes to be equal. Well, Excel doesn’t like that. In fact, it says “Uh, no” when you try to do this with a spreadsheet. That’s all well and good. But what about when you get this error running VBA code that used to work without a problem in Excel 2003?

    To answer this question you might want to take a look at your code. If you use a line of code with the .Move method this may well be your problem and here is why: if you are creating a separate workbook on the fly during your code operation, maybe for concatenating or manipulating data, and then later attempting to move a sheet from the newly created workbook into the legacy 2003 and earlier XLS file from which you are running the code, then you’re going to get this error. Why? When you run the code from Excel 2003 or earlier, any new workbooks created while running your code are also of the legacy format. But when you run the same macro in Excel 2007 or 2010 from the XLS file, you are creating a new XLSX metro workbook type and then telling Excel to stuff the larger page into the smaller one by issuing the move or copy command.

    Fine, so how do we work around this situation? There are a couple of ways. First, you can open the XLS file that contains the macro and click File > Save As before you run the macro. Save the file as an XLSM file type (metro file with a macro). Then when running the macro, you are working two equally–sized workbooks. You can then do another “Save As” to save the file back to the XLS legacy file format. The only drawback here is if you exceed the allowable rows and/or columns for legacy files.

    Another workaround would be to use a copy and paste instead of a move or copy to copy the data that you need and paste that data into the XLS spreadsheet. Of course there are a couple of caviats with this solution. First, if you’re copying more than 65,536 rows of data or more than 256 columns of information then you won’t be able to paste it into the XLS file. You would get the same error message. Second, the code to copy and paste only the data you need is more involved than a one-line ‘Sheets.Move’ statement.

    Hopefully, this will shed some light on why you might be encountering this error in VBA code. Let me know if you have any questions!

  • Will Buffington's WebLog

    Excel 2010 is slow to save to a remapped “My Documents” folder on the network

    • 4 Comments

    Here’s the problem. On a Windows 7 or Windows 2008 Server R2 machine, if you save your Excel 2010 documents into a My Documents (or subfolder like My Pictures) that has been re-mapped to a network location you may notice that it takes almost 40 seconds for the save to complete. The behavior is not consistent, however, as the latency does not occur every time you hit the save button.

    Fortunately, there is a fix for this problem.

    Apparently this was a known issue with Windows 7 and Windows 2008 R2, but the KB article to which this applies doesn't give any indication of the symptom, which is why I never found it. The hotfix contains an update for a Windows 7 networking driver which is causing the problem.

    The technical explanation: Excel 2010 makes an API call to Windows via a background thread which is waiting for the network driver to respond, which doesn't happen. The thread then times out and the save operation completes.

    Solution:

    1. Go to http://support.microsoft.com/kb/981711yes, that is the right KB article, even though the title talks about a stop error. Click the 'View and Request Hotfix Downloads' link at the top. Important: If you are downloading this hotfix for a computer other than the one you are viewing the article from then pay close attention to the link next to Step 1 on that page - the page uses an auto-detection script to determine if you are on x86, x64 or I64 systems. If you are wanting to apply this fix to an x86 machine and you are downloading from an x64 machine the hotfix you will receive by default is an x64 hotfix. If you click that link it will show all three hotfix types available.

    If you aren't sure which kind of machine you need it or, click the Start button and right click 'Computer' and left click on 'Properties'. Under 'System' the 'System type' will tell you what kind of operating system you are running.

    2. Once you have the hotfix for the machine, just double click it. The exe file that you download will extract an MSU file to a directory you specify. After that's done, double click the extracted .MSU file to run it. A system reboot WILL be necessary in most cases.

    After the hotfix is applied you should no longer see the save problems. I applied the hotfix to the test machine I had set up and the problem did go away.

  • Will Buffington's WebLog

    Corel Paint Shop Pro Photo X2 fails to update – Error 1920.Service ProtexisLicensing failed to start

    • 15 Comments

    This is an interesting error. If you own Corel Paint Shop Pro X2 you get prompted to install updates. In this case, the update fails to install and throws this nice dialog – “Error 1920.Service.ProtexisLicensing (ProtexisLicensing) failed to start. Verify that you have sufficient privileges to start system services.”

    image

    As you might have guessed, this problem doesn’t have anything to do with privileges. However it does have to do with the ProtexisLicensing service. If you open up the Services snap-in and look for this service you’re likely to find the ProtexisLicensing service – in the STARTING state.

    image

    That’s a problem. Starting means the service is neither started nor stopped. In fact, if you try to stop or restart this service you get an error that the service is currently busy.

    The way to get past this error is to open Task Manager (START, RUN and type TASKMGR and hit ENTER) and click the Processes tab. Find PSIService.exe in the list. Left click it once to highlight it and then click the End Process button. This will kill the PSIService and the ProtexisLicensing service will be in the stopped state. Now you can go back to the Services snap-in and start the service manually. After it has started, you can click the RETRY button in the error dialog and the update should finish.

  • Will Buffington's WebLog

    How to embed a manifest to an EXE file

    • 1 Comments

    This post explains in detail how to embed a manifest file into an executable (EXE) file. Embedding manifest files to EXEs is a requirement for the 'Certififed for Windows Vista' program (http://download.microsoft.com/download/8/e/4/8e4c929d-679a-4238-8c21-2dcc8ed1f35c/Windows%20Vista%20Software%20Logo%20Spec%201.1.doc)

    For the purposes of this article, the term 'appname' refers to a sample application and should be replaced with the name of your application.

    1. In Visual Studio 2005, open your application and go to the configuration manager. If you have x86 there already, click the drop down next to it and click <Edit…>. Find x86 in the list, select it and click Remove, the click Close. Now under Platform, click the drop down and select <New…>. Under New Platform, click the drop down and select x86. Under ‘Copy Settings From’, click the drop down and select <Empty>. Make sure the ‘Create New Solution Platforms’ checkbox is NOT checked. Click OK and Close to exit the configuration manager. Note: If you are using a post-build script to call MT.exe remove it as we will not need to use MT.exe to embed the manifest file.

    2. Rebuild the application.

    3. In VS 2005, click File, Close Solution.

    4. Open notepad and paste the following into the new document:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
         <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
              <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                   <security>
                        <requestedPrivileges>
                             <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
                        </requestedPrivileges>
                   </security>
             </trustInfo>
    </assembly>

    5. Click File, Save As and save this file as appname.exe.manifest where ‘appname’ is the name of the application you built in Step 1. Close the file.

    6. In VS 2005, click File, Open, File and browse to the location of your bin directory or where your EXE output is built and open appname.exe

    7. In the main Visual Studio 2005 window you should see a treeview with appname.exe – expand that by clicking the plus (+) sign. Underneath you should have at least two nodes for ‘Icon’ and ‘Version’. Right click appname.exe and left click Add Resource. Click the Import button and browse to where you saved the file from Step 5 (the notepad file you named as appname.exe.manifest) and select it and click Open. You may need to change the Files of Type to All Files in order to see it. A ‘Custom Resource Type’ dialogue appears asking for a resource type – type RT_MANIFEST and click OK. This will add the manifest with a value of 101. Right click that manifest file and left click on Properties. Change the ID property from 101 to 1.

    NOTE: If you want to verify the XML in the manifest is correct, double click the manifest in the tree view to see the binary. The ASCII data will be on the far right side.

    8. Click File, Save and close the file.

    9. If the .EXE file(s) you are working with is part of a ClickOnce deployment project you will need to update the ClickOnce application manifest and deployment manifest files since embedding a manifest to the executable file will change the hash of the file you are working with. You can use MageUI or Mage to do this. If using Mage.exe, open a command prompt and navigate to the directory where Mage.exe is stored and execute two commands:

    mage.exe -u <path to appname.exe.manifest file>\appname.exe.manifest -Name "AppName" -Version 1.0.0.0 -FromDirectory <path to where the appname.exe.manifest exists> -cf <path to the .pfx file>\name.pfx -pwd "password if you used one"

    where 1.0.0.0 is the version of your application

    mage.exe -u <path to .application file>\appname.application -appm <path to appname.exe.manifest>\appname.exe.manifest -cf <path to the .pfx file>\name.pfx -pwd "password if you used one"

    10. You are finished embedding the manifest to the .EXE file.

  • Will Buffington's WebLog

    How to create an audio fade-in effect for embedded Windows Media Player

    • 0 Comments

    Recently this question was asked of me. How to do a fade-in effect for audio files. I assumed media player had a built in function to cover fading audio in and out when it starts. I looked, looked some more, looked harder and finally gave up. There didn't seem to be a way to do it. So I came up with my own way.

    This code sample increments the volume over time in increments of half a second. You need only paste the code into an HTML page and change the line Player.URL = "Goldfish.avi"; to point to your media content. Enjoy!

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML XMLNS:t="urn:schemas-microsoft-com:time">
    <HEAD>
    <TITLE>volume / mute Property</TITLE>
    <?IMPORT namespace="t" implementation="#default#time2">

    <STYLE>
        .time{ behavior: url(#default#time2);}
    </STYLE>
    <script type="text/javascript" language="JavaScript">
    <!-- This code accomplishes the delay functionality -->
       /** constructor
      
           @param duration integer seconds
           @param <optional> function to run while waiting.
          
        */
       function Pause(duration, busy){
          this.duration= duration * 1000;
          this.busywork = null; // function to call while waiting.
          this.runner = 0;

          if (arguments.length == 2) {
             this.busywork = busy;
          }

          this.pause(this.duration);

       } // Pause class

       /** pause method
      
           @param duration: integer in seconds
          
        */
       Pause.prototype.pause = function(duration){
          if ( (duration == null) || (duration < 0)) {return;}

          var later = (new Date()).getTime() + duration;

          while(true){
             if ((new Date()).getTime() > later) {
                break;
             }

             this.runner++;

             if (this.busywork != null) {
                this.busywork(this.runner);
             }

          } // while

       } // pause method

    function Play()
    {
    <!-- This function increases the volume with a delay of .5 seconds between each increase -->
     if (Player.playstate == 3){
      for (i = 0; i < 10; i++)
      {
          var p = new Pause(.5);
          Player.settings.volume = Player.settings.volume + 5;
      }
     }
     else
     {
     alert("Not hit");
     }
     alert(Player.settings.volume);        
    }
    function go()
    {
    <!-- This code starts the embedded player playing. Substitute the name of your media file in the -->
    <!-- first line below -->

     Player.URL = "Goldfish.avi";
     Player.controls.Play();
     return;
    }
    Player.on
    </SCRIPT>

    </HEAD>
    <BODY>
    <P><OBJECT  ID="Player" width="320" height="300"  CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6">
    <PARAM name = "Volume" value="1">
    <PARAM name = "AutoStart" value="-1">
    <param name="URL" value="">
    <param name="rate" value="1">
    <param name="balance" value="0">
    <param name="currentPosition" value="0">
    <param name="defaultFrame" value="">
    <param name="playCount" value="1">
    <param name="currentMarker" value="0">
    <param name="invokeURLs" value="-1">
    <param name="baseURL" value="">
    <param name="mute" value="0">
    <param name="uiMode" value="full">
    <param name="stretchToFit" value="0">
    <param name="windowlessVideo" value="0">
    <param name="enabled" value="-1">
    <param name="enableContextMenu" value="-1">
    <param name="fullScreen" value="0">
    <param name="SAMIStyle" value="">
    <param name="SAMILang" value="">
    <param name="SAMIFilename" value="">
    <param name="captioningID" value="">
    <param name="enableErrorDialogs" value="0">
    </OBJECT>
    <SCRIPT LANGUAGE = "JScript" FOR = "Player" EVENT = "PlayStateChange(NewState);">
       if(3 == NewState)
       {
        Play();
       }
    </SCRIPT>
    <BR><BR><INPUT  TYPE="BUTTON" NAME="BtnPlay" VALUE="Play" accesskey=p OnClick="go()">

    </BODY>
    </HTML>

  • Will Buffington's WebLog

    C++ in Visual Studio 2005 - Some Basics

    • 1 Comments

    If you've ever written VB.NET code and you've tried your hand at creating a C++ app then you probably know the frustration of how hard it is to get a simple C++ project running and working. Oh sure, 'Hello World' isn't so bad (partially because it can be pre-built for you in Visual Studio) but try to implement a function out of an API and your simple half hour project could easily turn into a two day project.

    The purpose of this blog is for those starting C++ in Visual Studio .NET 2005. For the purpose of this post, I'll include sample code that I wrote which makes use of msienumproducts from the Windows Installer API. This function will return a list, or enumerate, products installed by the Windows Installer on your machine. First, take a look at the function descriptor on this MSDN page: http://msdn2.microsoft.com/en-us/library/aa370101.aspx - we see the following to start:

     UINT MsiEnumProducts( DWORD iProductIndex, LPTSTR lpProductBuf );

    Here we see the declarator for MsiEnumProducts is of type UINT, an unsigned integer. That means when this function runs, it's going to return an integer value that will signify one of five things. The MSDN page does tell you what those five things are, but not their corresponding integers, so I'll list them below:

    • 1610 - ERROR_BAD_CONFIGURATION
    • 87 - ERROR_INVALID_PARAMETER
    • 259 - ERROR_NO_MORE_ITEMS
    • 8 - ERROR_NOT_ENOUGH_MEMORY
    • 0 - ERROR_SUCCESS (not really an error, this actually means it worked)

    This function takes two arguments to work properly. The first is iProductIndex, declared as a DWORD, and lpProductBuf, declared as a LPTSTR which is a typedef. Not providing these in your code will product a compilation error.

    Okay, so now that we know what the function is all about we can just slap it into our code and assign variables to it, right? Well, not exactly. Remember, C++ gives the user 'ultimate' control over the environment, which also means a lot more work needs to be done to make simple things work - the same things VB programmers could easily take for granted. The next thing you should take a look at is the requirements.

    First, the Version tells us what we need to even be able to use this method. Since this function is from the Windows API we need the Windows Installer.

    We need to reference the library (.lib) file. On the MSDN page we see the filename that we need is MSI.lib. So now let's add a reference to it in our project. You do that in your project by right clicking the project name in the Solution Explorer or through the Project, <ProjectName> Properties menu. Expand configuration properties, then expand Linker and click on the Input line item. To the right you should see 'Additional Dependencies'. You want to include the path and file name in quotes here. With most API calls, it's a good idea to have the SDK that correlates to them installed. In this case, hopefully you have the latest Platform SDK installed. If so, you can find this file under C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib and the file is msi.lib. So the path in quotes in the Additional Dependencies line would be:
    "C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\msi.lib"

    Failure to include the library file reference will result in an error when you build your project. In this case you get the following errors in the output window:

    Error 1 error LNK2001: unresolved external symbol _MsiEnumProductsW@8 MsiEnumProduct_Sample.obj 

    Error 2 fatal error LNK1120: 1 unresolved externals C:\Documents and Settings\<profile name>\My Documents\Visual Studio 2005\Projects\<Project Name>\Release\ProjectName.exe

    The last requirement, the DLL file, should already be met as MSI.DLL exists in the Windows\System32 folder on most machines. If it's not there, the Windows Installer won't run and you won't be able to install any Windows Installer based programs. Time to head to Windows Update and get the latest Windows Installer, eh?

    Now let's take a look at some sample code. In this example I created a Win32 console application.

    #include "stdafx.h"
    #include <windows.h>
    #include <msiquery.h>
    #include <iostream>
    #include <string>
    using namespace std;

    int main(){
         TCHAR ProductCode[40];
         UINT nResult;
         string errResult;
         for (int nIndex = 0;;nIndex++)
         {
              nResult = MsiEnumProducts(nIndex,ProductCode);
              if (nResult != ERROR_SUCCESS)
              {
                   if (nResult == 1610)
                        errResult = "ERROR_BAD_CONFIGURATION";
                   if (nResult == 87)
                        errResult = "ERROR_INVALID_PARAMETER";
                   if (nResult == 259)
                        errResult = "ERROR_NO_MORE_ITEMS";
                   if (nResult == 8)
                        errResult ="ERROR_NOT_ENOUGH_MEMORY";
                   cout << errResult << endl;
                   break;
             }
           _tprintf(TEXT(" %4d - %s\r\n"), nIndex, ProductCode);
        }
       cin.ignore();
       return 0;
    }

    I'm using two different ways to display results, cout and _tprintf. The reason I'm doing this is because cout will let me display standard text and strings, but it won't be able to cast TCHAR types to strings for display. All this code is doing is using the msiEnumProducts function to display the product code (TCHAR ProductCode[40]) at index number (int nIndex). We cycle through these from index number 0 on up in increments of 1 until msiEnumProducts returns ERROR_NO_MORE_ITEMS. ErrResult is set to the value of whatever error code msiEnumProducts gives us.

  • Will Buffington's WebLog

    Running chained MSI installations

    • 2 Comments

    Anyone who has tried to run two Windows Installer-based installations at the same time knows that you can't do this. Only one MSI-based installation can run at a time. So what if you need to run multiple MSI packages one after the other? There is an easy solution to this using vbscript.

    Consider the following code:

    ' ===================================================================== 

    Option Explicit

    runit()

    sub runit()

    Dim ret, oInstaller

    Set oInstaller = CreateObject("WindowsInstaller.Installer")

    ret = oInstaller.InstallProduct("c:\Testsetupfiles\testsetup1.msi", "")

    ret = oInstaller.InstallProduct("c:\Testsetupfiles\testsetup2.msi", "")

    ret = oInstaller.InstallProduct("c:\Testsetupfiles\testsetup3.msi", "")

    end sub
    ' ==========================================================================

    What we're doing here is simple. We create variables ret and oInstaller and then set oInstaller to an instance of a Windows Installer object. Then we use the WindowsInstaller.InstallProduct method to call the installations. Since we have three lines of code here making the call, we're running three different installations as you can see by the different file names. The last two lines beginning with "ret =" wait until the line above it has run completely to start the installation. This script allows you to specify a local directory where your MSI file resides or you can specify a UNC path such as \\ServerName\ServerShare\MSIName

    You can also expand on the above code to run the installations of all MSI files in a shared folder on the client machine. Consider the following:

    ' ==========================================================================

    Option Explicit

    runit()

    sub runit()
     On Error resume next
     dim FSO, ret, oInstaller
     dim fn, f, fc

     Set FSO = CreateObject("Scripting.FileSystemObject")
     Set oInstaller = CreateObject("WindowsInstaller.Installer")

     set f = fso.getfolder("C:\Testsetupfiles")
     set fc = f.files

     for each fn in fc
      ret = oInstaller.InstallProduct(f & "\" & fn.name & "", "")
     Next

    end sub

    ' ==========================================================================

    Though it looks more complex, it really isn't. We're setting instances of the File System Object (FSO) and Windows Installer (oInstaller) and declaring variables we'll need to ennumerate the files in the target directory.
    We set f equal to our target folder C:\TestSetupFiles. Again, this can be substituted for a UNC path to a share on the network. Then we set fc to all of the files in our directory (f). Finally, by using a for each loop we cycle through all of the files (fc), setting the currently cycled file to fn and then call the WindowsInstaller.InstallProduct method to run the installation. In this line of code

    ret = oInstaller.InstallProduct(f & "\" & fn.name & "", "")

    we're parsing the directory f, adding a backslash and then ending with the filename (fn.name). This will work for all MSI files in a given directory. I added the On Error Resume Next line in the code because it's possible you will have more than just MSI files in the specified folder and obviously you can't install a .TXT file.

  • Will Buffington's WebLog

    Common Team Foundation Server installation errors and possible resolutions

    • 4 Comments

    Team Foundation Server for VS.NET 2005 can be a difficult program to install. The best advice I can give is to follow the Install Guide as closely as possible. Still, even the most prepared machine can have problems. Below are some of the errors that can appear and their most common resolutions. The list will be updated as new errors and resolutions are discovered.

    TFS Installation

    • Error 26403 (Failed to get group 'WinNT://Localhost/STS_WPG' or failed to add user: TFSSERVICE to group STS_WPG)
      - There can be several causes for this error. Check the following:
      • Under Administrative Tools in the Control Panel, open Computer Management and check Groups. Make sure the STS_WG group exists. If not, this will need to be created and needs to include the TFSSetup, TFSService and TFSReports users, or whichever users you are using for setup.
      • Make sure that you do not have the SQL Server Desktop Engine (MSDE) or Windows Sharepoint Services for MSDE installed. Check Add/Remove Programs in the Control Panel. If it exists, remove it. Remove Windows Sharepoint Services 2.0 from the machine. Make sure you are installing Windows Sharepoint Services with SP2 that can be downloaded from the Microsoft web site. When doing the installation WSS 2.0, make sure you choose a server farm installation when it asks for the installation type.
    • Error 28804 (Setup cannot connect to the SQL Server 2005 Reporting Services report server) - This problem can happen if the machine you are installing to has multiple IP addresses, and the address that hosts the report server is not the same as the one to which DNS resolves the machine name. TFS setup will attempt to connect to the Report Server through the IP Address but if the address resolves to a secondary web site and not the report server, the request will fail with HTTP Status 404: Not Found.

      To resolve this problem, chang the IP address of the report server in IIS Manager (START, RUN, INETMGR) to match the machine name IP Address and retry the installation.
    • Error 28805 (Setup cannot finish the request to the SQL Server 2005 Reporting Service report server. Verify that the report server is installed and running and that you have sufficient privileges to access it) - Check the following to resolve this problem:

      1.  In the SQL Reporting Services Configuration Tool, click on the Database Setup tab and make sure
      you are using Windows Credentials. 
      2. Delete encryption keys in reporting service configuration if they exist. 
    • Error 28936 (the Team Foundation Server ServerStatus Web
      service failed with 404 HTTP NotFound status)- This error typically happens because you logged onto the machine with a domain account and then tried to install TFS with two local accounts. When doing TFS Setup you need to log into the machine on the local account that will be doing the install such as the local TFSSetup account (the account you will use for TFS Setup) or the admin account.
      • If the above fails, again check that Windows Sharepoint Services for MSDE is not installed.
    • Error 28925 (Calling the Team
      Foundation Server ServerStatus Web service failed) - This error has to do with DNS and connectivity. It is typically caused by the server name not resolving via DNS correctly. You can add the server name to the DNS server so that it resolves correctly. It can also be caused by the DNS server IPAddress not matching the other machines on the network. To check, go to START, RUN and type CMD. In the command prompt window type IPCONFIG /ALL and hit Enter. Then check the IP Address of the DNS server. Match this against the DNS Server of another machine on the network.
      • You can also check IIS to make sure nothing else is using port 8080. If you have something like Apache using port 8080, you will need to have it use a different port.

    • Error 20082 (Error Unknown) - There are a couple of known causes for this error. First and foremost, remember that when installing TFS you need to be logged in as a user that is under the same context as the TFSService and TFSReports accounts. To clarify - if the accounts that you will use for TFSService and TFSReports are domain accounts, then the account you use to setup TFS must also be a domain account and that's the account you need to be logged into. If the accounts you are using for TFSService and TFSReports are local machine accounts, then the account you use to setup TFS must be a local machine account and you must be logged in as that user. In either case, the account you use to setup TFS must have admin rights to the machine.

      Another possible cause for this error is that SQL Reporting Services is not configured correctly. Open the Reporting Services Configuration tool from Start, Programs (or All Programs), Microsoft SQL Server 2005, Configuration Tools. If you have red X's on Server Status, Report Server Virtual Directory, Report Manager Virtual Directory, Windows Service Identity, Web Service Identity, Database Setup or Initialization, you will need to resolve these before you can install. You can also start up the IIS configuration tool by going to START, RUN and type INETMGR. Expand the local computer. You should see Application Pools. Look under the Default Application Pool. Make sure ReportServer is listed in the Application Pool. Also, right click Report Server, left click properties and go to the Identity tab. Make sure this is set to run under the local system account.

    • Error 29112 (Report server service not configured properly) - This error can have multiple causes. Check the following:

      1. Reporting Services isn't configured properly, like the error says. Open the Reporting Services Configuration tool (Start, Programs, Microsoft SQL Server 2005, Configuration Tools). If you don't have green checks all the way down to and including Initialization (with the exception of Encryption Keys) then this is most likely the problem. Check the following:

      Server Status - If not Running, click the START button in the middle of the page

      Report Server Virtual Directory - Name should read Report Server; Website should read Default Web Site

      Report Manager Virtual Directory - Name should read Reports; Website should read Default Web Site

      Windows Service Identity - Service Name should read Report Server; Service Account should read LocalSystem; Built In Account should be selected with Local System in the drop down box

      Web Service Identity - ASP .NET Service Account should read NT Authority\Network Service; Report Server should read ReportServer; Report Manager should read ReportServer

      Database Setup - Server Name should be the name of the machine; Database Name should read ReportServer; Credentials Type should read Service Credentials

      Initialization - The machine name should be listed with the SQL Server, the ID and the Initialized check box checked. If not checked, select the instance and click the Initialize button

      2. Make sure that the Default Application Pool in IIS Manager is set to run under the Network Service Account (Start, Run, type INETMGR, click OK. Right click Default App Pool, Properties, Identity tab)

    • Error 32000 - This is one of those all-inclusive errors that looks really intimidating when you see it because the error itself contains a really big freaking number. 32000 comes in many flavors. It's the very end of the error that you want to look at right after the words 'non 0 value: or 'non-zero value'.
      • non zero value: -2130246810 -
        • In INETMGR, right click the Default web site and left click on Properties. On the Directory Security tab, click Edit and make sure that Integrated Windows Authentication is being used.
        • In INETMGR, right click the Default web site and left click on Properties. Go to the Web Site tab. Make sure the IP Address field under Web Site Identificaiton is set to 'All Unassigned'.
      • non zero value:-2130242250 or -1 -
        • There isn't much info on this error, just that it is normally caused by a bum installation of Windows Sharepoint Services 2.0. Try removing it from ARP (Add/Remove Programs) and reinstall.
      • non zero value: -4 or -5
        • This one is typically a problem with SQL Reporting Services. Check the Reporting Services Configuration tool to make sure that you have green check marks for all items.
        • Open Internet Explorer and in the Address Bar, type http://machinename/reports to bring up the Reporting Services reports. If you bring up a 'Page cannot be displayed' or 401 or 404 error then Reporting Services is not correctly configured.

    I'll post more errors and solutions as they become available.

  • Will Buffington's WebLog

    Customer feedback and suggestions for VS.NET 2005 and MSDN 2005

    • 2 Comments

    Below are listed some feedback taken directly from customers supported by Microsoft on ways to improve Visual Studio .NET 2005 and MSDN 2005 (please feel free to email me to add more to this list or comment the blog directly):

    • Users should be warned prior to starting setup that the setup may take more than an hour to complete
    • Instead of saying “this may take several minutes” during the MSDN installation, the user should be prompted with an actual or estimated time remaining
    • The MSDN maintenance mode installation should allow a user who has performed a minimal install to go back and select a full install later on, which it currently does not. You must uninstall MSDN and then reinstall using the full option.
    • During the install, when you enter a product key that is good but for a different version of VS.NET you are told that the key is invalid the first time you launch Visual Studio .NET 2005. This problem existed as one of the top ten issues back in VS.NET 2002 and 2003. Customers would like to be prompted to enter a valid product key instead of having to uninstall VS.NET 2005 and reinstalling it with the new key. 
  • Will Buffington's WebLog

    Using the ServiceInstall Table to install a Windows Service with custom properties

    • 2 Comments

    You know how when you build a Windows Service and then include a setup and deployment project with your application and then during the installation a Log in screen appears? There may come a time when you want to install a Windows Service silently and not see that log in screen.

    First, I need to point out that the Windows Installer and the installer for the Windows service are two separate entities and Windows Installer has no influence on the service except to run the EXE. I've also tried passing properties to a service installer EXE manually but was not successful.

    You have to remember that Visual Studio .NET in intended to build quick and simple MSI packages, nothing real involved, so it won't be of much help to us here. What I've found that does work is using ORCA to modify the MSI package and populate the ServiceInstall table with information needed to make your request work. To do that, please follow these steps:
     
    1. Open your service/setup project in VS.NET. Remove the ServiceProcessInstaller and the ServiceInstaller from your project.
     
    2. Build your MSI package.
    3. I have attached a ZIP file containing a program called ORCA. In the ZIP file is a file, Orca.MSI that you will need to install.
    4. Once you have installed Orca, go to the folder that contains your MSI file. Right click the MSI package and then left click on Open with Orca.
    5. With the Orca program open, scroll down to the Property table on the left side and click it once to highlight it. Double click the first empty row in the right side of this table. We're going to create two new property values. For the first one, in the Property field enter any name, like USERNAME_FIELD and in the Value column enter NONE. Then click OK. Double left click the next empty row and follow the same instructions for creating a value for our password field. Call it something like PASSWORD_FIELD or whatever you prefer. These values will take the place of the UserName and Password prompts that you are used to seeing in the pop up dialog when you install a Windows service.
    6. With the Orca program open, scroll down on the left side to the ServiceInstall table and click it once to highlight it. Double click the first empty row on the right side and populate the fields with the following info:
     
    (info on the ServiceInstall table can be found at
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/serviceinstall_table.asp)
     
    ServiceInstall - This is a primary key and can be set to any unique value such as 123123123ABC or ServiceTest1234567890
     
    Name - This column is the string that gives the service name to install. The string has a maximum length of 256 characters. The service control manager database preserves the case of the characters in the service name, but comparisons of service names are case insensitive. Forward-slash (/) and back-slash (\) are invalid service name characters.
     
    Display Name - This column is the localizable string that user interface programs use to identify the service. The string has a maximum length of 256 characters. The service control manager preserves the case of the display name, but display name comparisons are case insensitive.
     
    ServiceType - 16 (see the ServiceType documentation in the link provided for tables that describe what these values are for)
     
    StartType - 2 (see the StartType documentation in the link provided for tables that describe what these values are for)
     
    ErrorControl - 1 (see the ErrorControl documentation in the link provided for tables that describe what these values are for)
     
    LoadOrderGroup - (this can be left blank)
     
    Dependencies - (this can also be left blank)
     
    StartName
    - This will be one of the properties you created in the previous step that corresponds to the Machinename\Username that you would normally enter in the service install window that pops up. The property name needs to be included in square brackets, so for example, if you had a property name of USERNAME_FIELD it should be entered as [USERNAME_FIELD]
     
    Password - This will be the other property that you created corresponding to the password for the previously mentioned machinename\username. Since it references a property, it should also be included in square brackets. For example, if the property name you created was PASSWORD_FIELD the value you entered would be [PASSWORD_FIELD]
     
    Arguments - (This field can be left blank)
     
    Component - This needs to be set to the same value that's in the first column of the Component Table for the service that you are installing. If you aren't sure which component value is for your service, look at the File table, you should see the executable for your service in the FileName column. The corresponding value in the Component column of this table will be the same as the Component column of the Component table.
     
    7. Click File, Save at the top to save your changes. Note: Don't use the Save As option in ORCA as it incorrectly strips out information that we will need.
     
    8. Now all that's left to do is install your MSI package. Try running it silently and passing the two property values that we created from a command prompt. The syntax will be something like:
     
    C:\ServiceInstallTest.MSI /Q USERNAME_FIELD=MACHINENAME\USERNAME PASSWORD_FIELD=PASSWORD
     
    where USERNAME_FIELD and PASSWORD_FIELD are the property values we created in Orca.
     
    9. You can monitor the MSI Progress by looking as Task Manager (START, RUN, type TASKMGR) and looking at the Processes tab for MSIEXEC.EXE - you might see several of them running and that's normal.
     
    10. After they disappear, you know the installation is complete. Go to START, RUN and type SERVICES.MSC and click OK to view the services and you should see your service in the list.
Page 1 of 1 (11 items)