Buck Hodges

Visual Studio Online, Team Foundation Server, MSDN

Posts
  • Buck Hodges

    Team Foundation Version Control command line summary

    • 0 Comments
    Rob Caron put together a very nice one-page command line summary for h.exe.  I've posted it as an article (Team Foundation Version Control Command Line Summary document).  Check it out if you want to see the list of command and options for h.exe.
  • Buck Hodges

    Team Foundation Version Control Command Line Summary document

    • 2 Comments

    Command line summary for tf.exe.  This was put together by Rob Caron.

    You may also want to see the full Team Foundation Version Control Command Line Reference as well.

    This is pre-release documentation and is subject to change in future releases.

    Command

    Usage

    Add

    tf Add itemspec [lock:none|checkin|checkout] [/type:filetype] [/noprompt] [/recursive]

    Branch

    tf Branch olditem newitem [/version:versionspec] [/noget] [/lock] [/noprompt] [/recursive]

    Branches

    tf branches [/s:servername] itemspec

    Changeset

    tf Changeset [/comment:comment|@commentfile] /s:servername [/notes:(“NoteFieldName”=”NoteFieldValue”|@notefile)] [/noprompt] ([/latest]|changesetnumber)

    Checkin

    tf checkin [/author:authorname] [/comment:("comment"|@commentfile)] [/noprompt] [/notes:(“Note Name”=”note text”|@notefile)] [/override:reason|@reason] [/recursive] filespec …]

    Checkout

    tf checkout [/lock:(none|checkin|checkout)] [/recursive] [/type:encoding] itemspec

    Delete

    tf delete [/lock:(none|checkin|checkout)] [/recursive] itemspec

    Difference

    tf difference itemspec [/version:versionspec] [/type:filetype] [/format:(visual|unix|ss)] [/ignorespace] [/ignoreeol] [/ignorecase] [/recursive] [/options:"options"]

     

    tf difference itemspec itemspec2 [/type:filetype] [/format:(visual|unix|ss)] [/ignorespace] [/ignoreeol] [/ignorecase] [/recursive] [/options:"options"]

     

    tf difference [/shelveset:shelvesetname;[shelvesetowner]] shelveset_itemspec [/server:serverURL] [/type:filetype] [/format:(visual|unix|ss)] [/ignorespace] [/ignoreeol] [/ignorecase] [/recursive] [/options:"options"]

    Dir

    tf dir [/s:servername] itemspec [/version:versionspec] [/recursive] [/folders] [/deleted]

    Get

    tf get itemspec [/version:versionspec] [/all] [/overwrite] [/force] [/preview] [/recursive] [/noprompt]

    Help

    tf help commandname

    History

    tf history [/s:servername] itemspec [/version:versionspec] [/stopafter:number] [/recursive] [/user:username] [/format:(brief|detailed)] [/slotmode]

    Label

    Option Set 1:

    tf label [/s:servername]  labelname@scope [/owner:ownername] itemspec [/version:versionspec] [/comment:("comment"|@commentfile)] [/child:(replace|merge)] [/recursive]

     

    Option Set 2:

    tf label [/s:servername] [/delete]  labelname@scope [/owner:ownername] itemspec [/version:versionspec] [/recursive]

    Labels

    tf labels [/owner:ownername] [/format:(brief|detailed)] [/s:servername] [labelname]

    Lock

    tf lock itemspec /lock:(none|checkout|checkin) [/workspace:workspacename] [/server:serverURL] [/recursive] [/noprompt]

    Merge

    tf merge  [/recursive] [/force] [/candidate] [/discard] [/version:versionspec] [/lock:none|checkin|checkout] [/preview] [/baseless] [/nosummary] source destination

    Merges

    tf merges [/s:servername] [source] destination [/recursive]

    Permission

    tf permission [/allow:(* |perm1[,perm2,]] [/deny:(* |perm1[,perm2,])] [/remove:(* |perm1[,perm2,])] [/inherit:yes|no] [/user:username1[,username2,]] [/recursive] [/group:groupname1[,groupname2,]] [/server:servername] itemspec

    Properties

    tf properties [/recursive] itemspec

    Rename

    tf rename [/lock:(none|checkout|checkin)] olditem newitem

    Resolve

    tf Resolve itemspec [auto:(AcceptMerge|AcceptTheirs|AcceptYours)] [/preview] [(/overridetype:overridetype | /converttotype:converttype)] [/recursive]

    Shelve

    tf shelve [/move] [/replace] [/comment:(@commentfile|"comment")] [/recursive] shelvesetname[;owner] filespec

     

    tf shelve /delete [/server:serverURL] shelvesetname[;owner]

    Shelvesets

    tf shelvesets [/owner:ownername] [/format:(brief|detailed)] [/server:serverURL] shelvesetname

    Status

    tf status itemspec [/s:servername] ([/workspace:workspacename[;workspaceowner]] | [/shelveset:shelvesetname[;shelvesetowner]]) [/format:(brief|detailed)] [/recursive] [/user:(*|username)]

    Undelete

    tf undelete [/noget] [/lock:(none|checkin|checkout)] [/newname:name] [/recursive] itemspec[;deletionID]

    Undo

    tf undo [/workspace:workspacename[;workspaceowner]] [/s:servername] [/recursive] itemspec

    Unlabel

    tf unlabel [/s:servername] [/recursive] labelname itemspec

    Unshelve

    tf unshelve [/move] [shelvesetname[;username]] itemspec

    View

    tf view [/s:servername] [/console] [/noprompt] itemspec [/version:versionspec]

    WorkFold

    tf workfold localfolder

     

    tf workfold [/workspace: workspacename]

     

    tf workfold [/s:servername] [/workspace: workspacename] repositoryfolder

     

    tf workfold [/map] [/s:servername] [/workspace: workspacename] repositoryfolder|localfolder

     

    tf workfold /unmap [/s:servername] [/workspace: workspacename] [/recursive] (repositoryfolder|localfolder)

     

    tf workfold /cloak (repositoryfolder|localfolder) [/workspace: workspacename] [/s:servername]

     

    tf workfold /decloak (repositoryfolder|localfolder) [/workspace: workspacename] [/s:servername]

    Workspace

    Option Set #1--Create New Workspace:

    tf workspace /new [/noprompt] [/template:workspacename[;workspaceowner]]

    [/computer:computername] [/comment:(“comment”|@commentfile)] [/s:servername]

     

    Option Set #2--Delete Workspace:

    tf workspace /delete [/s:servername] workspacename[;workspaceowner]

     

    Option Set #3--Edit Existing Workspace:

    tf workspace [/s:servername] [/comment:comment] [/newname:workspacename] workspacename[;workspaceowner]

    Workspaces

    tf workspaces [/owner:ownername] [/computer:computername] [/s:servername] [/format:(brief|detailed)] [/updateUserName:oldUserName] [/updateComputerName:oldComputerName] workspacename

     

    tf workspaces /remove:(*|workspace1[,workspace2,...]) /server:(*|server)

  • Buck Hodges

    Setting Internet Explorer's home page by drag and drop

    • 4 Comments

    Tim, who worked on IE among other things in his career at Microsoft and now works on Hatteras, showed me tonight that you can set the home page in Internet Explorer by dragging the link from the Address bar to the Home icon on the toolbar.  I had no idea.  I burst out laughing.  It's a neat trick once you know it, but it never occurred to me.  Perhaps it's because I don't change my home page.

    Someone's going to tell me that it's obvious, and I'm the only who didn't know about it.  Right.  It's an example of something that's really convenient, if you need that sort of thing, but not very discoverable (unless you often drag things over toolbar buttons just to see what happens).

  • Buck Hodges

    Timeouts on the HttpWebRequest (and thus SOAP proxies)

    • 5 Comments

    Last summer I wrote several posts on using HttpWebRequest and SOAP proxies.  Recently I was working on code that needed to handle requests that could take a really long time for the server to process.  The client would give up and close the network connection long before the request completed.

    The code had tried to control that using the HttpWebRequest.Timeout property.  That helped, but it didn't solve the problem.  Without changing the Timeout property, the client gave up after 100 seconds, which is the default value for that property as stated in the docs.  The Timeout property was set to infinite, but the client gave up after five minutes.  Below is the doc for the Timeout property.

    Return Value

    The number of milliseconds to wait before the request times out. The default is 100000 milliseconds (100 seconds).

    Remarks

    Timeout is the number of milliseconds that a synchronous request made with the GetResponse method waits for a response, and the GetRequestStream method waits for a stream. If the resource is not returned within the time-out period, the request throws a WebException with the Status property set to Timeout.

    The Timeout property has no effect on asynchronous requests made with the BeginGetResponse or BeginGetRequestStream methods.

    Caution In the case of asynchronous requests, it is the responsibility of the client application to implement its own timeout mechanism. Refer to the example in the BeginGetResponse method.

    To specify the amount of time to wait before a read or write operation times out, use the ReadWriteTimeout property.

    At the end of that, notice that they mention another timeout value, the HttpWebRequest.ReadWriteTimeout property.  Here's the doc for that.

    Return Value

    The number of milliseconds before the writing or reading times out. Its default value is 300000 milliseconds (5 minutes).

    Remarks

    The ReadWriteTimeout is used when writing to the stream returned by GetRequestStream or reading from the stream returned by GetResponseStream.

    Specifically, the ReadWriteTimeout property controls the time-out for the Read method, which is used to read the stream returned by the GetResponseStream method, and for the Write method, which is used to write to the stream returned by GetRequestStream method.

    To specify the amount of time to wait for the request to complete, use the Timeout property.

    Well, there's the five minute timeout.  If you want to wait for a long request, which is greater than five minutes for the HttpWebRequest, you need to set both properties.  Using the information in the post from the summer, you can add code to your override of GetWebRequest() in your SOAP proxy to set the timeout to an hour, for example, using request.Timeout = 3600 * 1000 and request.ReadWriteTimeout = 3600 * 1000.

    You may also notice that the Timeout property doesn't apply to asynchronous calls that use the Begin/End call pattern.  For those, only the ReadWriteTimeout applies.

  • Buck Hodges

    Are you looking to convert from ClearCase to Team Foundation?

    • 2 Comments

    The Program Manager for the ClearCase converter, Akash Maheshwari, wants to hear from Clearcase users interested in VSTS.  If you are a ClearCase user, this is your chance to influence the development of the converter.

  • Buck Hodges

    Branching and Merging in the Dec. CTP

    • 2 Comments

    Back in the summer I wrote several posts on branching and merging in Team Foundation Source Control.  They are also relevant for the Dec. CTP if you are interested in this very important part of SCM.

  • Buck Hodges

    How to delete a team project in the Dec. CTP

    • 2 Comments
    Someone in the newsgroup asked how to delete a team project.  I asked James and he mentioned DeleteTeamProject.exe.
     
    From a Visual Studio command prompt, you can use the following command line app to delete a project.  To get the command prompt, go to Start -> All Programs -> Microsoft Visual Studio 2005 Beta -> Visual Studio Tools -> Visual Studio Command Prompt.
     
    Note that the /domain option is just the name of your Team Foundation server that you see in Team Explorer and is only necessary if you set up more than one Team Foundation server.
     
    Example:
       DeleteTeamProject MyProject
     
    Help:
    DeleteTeamProject.exe
    Usage:
     
    DeleteTeamProject [/q] [/domain:<domainName>] <project name>
     
        [/q]  - Quiet mode.  Do not prompt the user for confirmation.
        [/domain:<domainName>] The name of the domain.  Necessary in multi-domain environments.
        <project name> The name of the project.  Use quotation marks if there are spaces in the name.
     
    Deletes the Portfolio Project from Team System.  After deletion, the project may not be recovered.  Use with caution.  Required permission: DELETE on the project.
    [Update] DeleteTeamProject is not in the path for the command prompt.  The app is in <your drive>:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies.
  • Buck Hodges

    VSTS and MSDN Universal

    • 11 Comments

    Back in June I posted information from the newgroup regarding VSTS Pricing.

    Here's an update from Ajay Sudan's newsgroup post (Jan. 24, 2005).

    MSDN Universal customers may migrate to their choice of
    Visual Studio Team Architect Edition, Visual Studio Team
    Developer Edition, or Visual Studio Team Test Edition at
    no additional cost for the duration of their MSDN
    Universal subscription.

    MSDN Universal customers may also elect to migrate to
    Visual Studio Team Suite at an additional cost. Detailed
    pricing/licensing for Visual Studio Team System will be
    announced in early March.
  • Buck Hodges

    Team Foundation Source Control client API example

    • 16 Comments

    Here's a really simple example that uses the source control API () in the Dec. CTP.  It shows how to create a workspace, pend changes, check in those changes, and hook up some important event listeners.  This sample doesn't do anything useful, but it should get you going.

    You'll need to reference the following dlls to compile this example.
    System.dll
    Microsoft.VisualStudio.Hatteras.Client.dll
    Microsoft.VisualStudio.TeamFoundation.Client.dll

    If you write something with the API, please send me email or leave a comment.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using Microsoft.VisualStudio.Hatteras.Client;
    using Microsoft.VisualStudio.TeamFoundation.Client;

    namespace BasicSccExample
    {
        class Example
        {
            static void Main(string[] args)
            {
                // Verify that we have the arguments we require.
                if (args.Length < 1)
                {
                    Console.Error.WriteLine("Usage: app tfsName");
                    Environment.Exit(1);
                }

                // Get a reference to our Team Foundation Server.
                String tfsName = args[0];
                TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(tfsName);

                // Get a reference to Source Control.
                SourceControl sourceControl = (SourceControl) tfs.GetService(typeof(SourceControl));

                // Listen for the Source Control events.
                sourceControl.NonFatalError += Example.OnNonFatalError;
                sourceControl.Getting += Example.OnGetting;
                sourceControl.BeforeCheckinPendingChange += Example.OnBeforeCheckinPendingChange;
                sourceControl.NewPendingChange += Example.OnNewPendingChange;

                // Create a workspace.
                Workspace workspace = sourceControl.CreateWorkspace("BasicSccExample", sourceControl.AuthenticatedUser);

                try
                {
                    // Create a mapping.
                    workspace.CreateMapping("$/", @"c:\temp\BasicSccExample");

                    // Get the files from the repository.
                    workspace.Get();

                    // Create a file.
                    String topDir = Path.Combine(workspace.Folders[0].LocalItem, "sub");
                    Directory.CreateDirectory(topDir);
                    String fileName = Path.Combine(topDir, "basic.cs");
                    using (StreamWriter sw = new StreamWriter(fileName))
                    {
                        sw.WriteLine("revision 1 of basic.cs");
                    }

                    // Now add everything.
                    workspace.PendAdd(topDir, true);

                    // Show our pending changes.
                    PendingChange[] pendingChanges = workspace.GetPendingChanges();
                    Console.WriteLine("Your current pending changes:");
                    foreach (PendingChange pendingChange in pendingChanges)
                    {
                        Console.WriteLine("  path: " + pendingChange.LocalItem +
                                          ", change: " + PendingChange.ChangeTypeToString(pendingChange.ChangeType));
                    }

                    // Checkin the items we added.
                    int changesetNumber = workspace.CheckIn(pendingChanges, "Sample changes");
                    Console.WriteLine("Checked in changeset " + changesetNumber);

                    // Checkout and modify the file.
                    workspace.PendEdit(fileName);
                    using (StreamWriter sw = new StreamWriter(fileName))
                    {
                        sw.WriteLine("revision 2 of basic.cs");
                    }

                    // Get the pending change and check in the new revision.
                    pendingChanges = workspace.GetPendingChanges();
                    changesetNumber = workspace.CheckIn(pendingChanges, "Modified basic.cs");
                    Console.WriteLine("Checked in changeset " + changesetNumber);
                }
                finally
                {
                    // Delete the items.
                    workspace.PendDelete("$/*", RecursionType.Full);
                    PendingChange[] pendingChanges = workspace.GetPendingChanges();
                    if (pendingChanges.Length > 0)
                    {
                        workspace.CheckIn(pendingChanges, "Clean up!");
                    }

                    // Delete the workspace.
                    workspace.Delete();
                }
            }

            internal static void OnNonFatalError(Object sender, ExceptionEventArgs e)
            {
                if (e.Exception != null)
                {
                    Console.Error.WriteLine("Non-fatal exception: " + e.Exception.Message);
                }
                else
                {
                    Console.Error.WriteLine("Non-fatal failure: " + e.Failure.Message);
                }
            }

            internal static void OnGetting(Object sender, GettingEventArgs e)
            {
                Console.WriteLine("Getting: " + e.TargetLocalItem + ", status: " + e.Status);
            }

            internal static void OnBeforeCheckinPendingChange(Object sender, PendingChangeEventArgs e)
            {
                Console.WriteLine("Checking in " + e.PendingChange.LocalItem);
            }

            internal static void OnNewPendingChange(Object sender, PendingChangeEventArgs e)
            {
                Console.WriteLine("Pending " + PendingChange.ChangeTypeToString(e.PendingChange.ChangeType) +
                                  " on " + e.PendingChange.LocalItem);
            }
        }
    }

  • Buck Hodges

    How to use shelving from the command line

    • 4 Comments

    Shelving is a really useful feature that was included for the first time with the Dec. CTP.  Shelving allows you to save your changes to a shelveset on the server.  The shelveset consists of the same kind of information that a checkin does, except that you aren't checking in.  You don't create a new changeset.  Rather, you create a space on the server that is your own that contains your pending changes, comment, etc.

    You can choose to move your changes out of your workspace or you can keep your pending changes when you shelve.  Moving your changes is great when you need to stop working on your current changes, make a targeted fix, check in that fix, and then unshelve what you were working on before being interrupted.  Keeping your changes in your workspace is very useful when you want share a change (perhaps a fix for another developer prior to checkin) or have another person review your changes.

    I'll talk more about how works in upcoming posts.  For now, here are some commands you can use to explore shelving in the Dec. CTP.

    Bring up a Visual Studio command prompt (Start -> All Program -> Microsoft Visual Studio 2005 Beta -> Visual Studio Tools -> Visual Studio Command Prompt), cd to a workspace directory with some pending changes, and try out some of the following.  If you need to create a workspace, you can create one with "h workspace /new MyWorkspace /s:yourtfsservername" and then pend some changes.

    To shelve all of your changes in your current workspace, use
        h shelve MyShelvesetName [optional filespecs]

    To unshelve an existing shelveset, use
        h unshelve MyShelvesetName [optional filespecs]

    To shelve the changes and undo them in your workspace, use the /move option with /i (or uncheck "Preserve my changes" in the GUI).  The /move option also deletes pending adds since they get uploaded to the server -- something a plain undo doesn't (and can't) do.
        h shelve /i /move shelvesetname [optional filespecs]

    To delete a shelveset, use the shelve command.
        h shelve /delete shelvesetname

    To see the changes in another user's shelveset, use the status command (when the other user is in the same domain, you should be able to leave that off).
        h status /shelveset:shelvesetname;domain\user

    To see the diffs for a shelveset, use the diff command (great for remote code reviews).
        h diff /shelveset:shelvesetname;domain\user

    You can also see a list of all shelvesets with shelvesets command
        h shelvesets /owner:*

     

  • Buck Hodges

    Problems with large files and the Dec. CTP in Team Foundation Version Control

    • 2 Comments

    If you try, as one person in the Team Foundation newsgroup did, to checkin large files (>200 MB or so), you will reach a point where it fails with a message like "there is not enough storage to complete this command."  That is due to the fact that the Dec. CTP uses the MSPatch library to compress files for upload.  The working set will grow proportionally with the size of the file, and the process will run out of memory.

    The design goal for Team Foundation Version Control is to support up to 2 GB files (size after compression).  We have switched from MSPatch to the new GZip (okay, nothing's written in stone, so keep in mind that it's true while I'm typing) support built into the Whidbey framework.  The result is that the working set grows by only about 5 MB or so regardless of file size, and it's faster for larger files.

    We were really pushing MSPatch into a role for which it was probably not intended.  It's more suited for an environment where minimizing the compressed file is the primary goal while sacrificing run time and memory.

    Using GZip will make life easier for folks like SourceGear who want to write non-Windows clients for Team Foundation.

  • Buck Hodges

    Checkin policies and the December CTP

    • 1 Comments

    Problem with CleanBuildPolicy in the December CTP

    When you try to configure a new checkin policy, you will get an error regarding the CleanBuildPolicy.  That policy has a problem due to it or one of its dependencies not being properly signed.  You can work around the problem by removing it from the registry by deleting the following key.
        HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Hatteras\Checkin Policies\CleanBuildPolicy

    How to write a checkin policy

    If you would like to write your own checkin policy, you'll want to read Jim Presto's blog.  He has posted information on how to do it along with the code.

    What is the Team Build error dialog about?

    If you get a message dialog about a problem with Team Build, you can safely ignore it.  It's not fully functional in the December CTP.

  • Buck Hodges

    More on setting up a Win2k3 Domain Controller for the December CTP

    • 1 Comments
    In addition to Paul Murphy's post mentioned earlier, Kevin Kelly included a link to the following TechNet article: Installing Windows Server 2003 as a Domain Controller.
  • Buck Hodges

    December CTP is available!

    • 5 Comments

    Since my last post ages ago was about a CTP release, I'll start back up again with a post to point to the December CTP.  This one is definitely an improvement over the last one, though it is clear we still have a ways to go.

    You may want to check out the newsgroups for VSTS.  There are a number of people there who post information based on their experiences that may make it easier for you.  This post from June has all the info you need to use the newsgroups.

    There are also some good weblog posts, such as Paul Murphy's post on setting up a domain controller.

    The December CTP is very, very close to what we are using internally now (what Microsoft likes to call dogfooding, which is a term some people take a little too far).  If you can get up and running (yes, you still need two machines), you should find it much more capable than before.

    [Update]  Don't forget to keep an eye out for answers to common problems on the Visual Studio Team System 2005 blog.  Over the next couple of weeks, you should see FAQs and the like as was the case with the September Beta 1 Refresh CTP.

  • Buck Hodges

    VSTS CTP release, including the Team Foundation portion this time

    • 1 Comments

    If you have access to the MSDN downloads or can get a hold of one the DVDs, you can now try out Hatteras and the rest of the Team Foundation along with the rest of Team System.  You'll need several machines to install the CTP release of Team System included in the VS2005 Beta 1 Refresh.

    This release is very close to what we use everyday.  Much of our source code for Team Foundation is stored in a Hatteras server, and we use Currituck for our bug tracking.  Microsoft likes to call it dogfooding, and some people really take the analogy way too far.  But it's certainly a great way for us to find out what it's like to use the product (I'm happy to report that it's been a good experience thus far).

    Having said that, you really should take the warning in the Readme file seriously.

    2.1.1 Community Technology Preview Build Quality

    Visual Studio 2005 Beta 1 Refresh with Visual Studio 2005 Team System is a Community Technology Preview build. These builds are not for everyone. Because our goal is to offer these builds as they are ready, very little effort is put into stabilizing them or ensuring their quality. Typically, our Beta and released products go through a rigorous testing and quality assurance process before they become available. These interim Community Technology Preview builds do not go through this process. It is very likely that removing the build will introduce significant instability to your installed system and may even cause you to need to reformat your drive. Therefore, do not install these builds on machines on which you depend. Specifically, uninstall of Team Foundation Server is not supported in this release.

    Be sure to take a look at Rob Caron's post on the CTP.

  • Buck Hodges

    Handling HTTP response codes in SOAP proxies

    • 4 Comments

    Continuing with the last post on authentication issues with wsdl.exe-generated SOAP proxies, you may need to handle HTTP status codes to provide custom exceptions.  To do this, the SoapHttpClientProtocol class (actually its parent HttpWebClientProtocol) provides a pair of GetWebResponse() methods for derived classes to override.  One method is for synchronous calls and the other for asynchronous.

    The following code shows how to generate a custom exception for the HTTP 401 Unauthorized code.

    using System;
    using System.Net;

    public class MyProxy : WsdlExeGeneratedProxy
    {
       protected override WebRequest GetWebRequest(Uri uri)
       {
          HttpWebRequest request = base.GetWebRequest(uri) as HttpWebRequest;
          request.Headers.Add("accept-language", CultureInfo.CurrentUICulture.Name);
          request.Credentials = m_state.Credentials;
          return request;
       }
       protected override WebResponse GetWebResponse(WebRequest request)
       {
          HttpWebResponse response = base.GetWebResponse(request) as HttpWebResponse;
          ThrowIfUnauthorized(response);
          return response;
       }
       protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
       {
          HttpWebResponse response = base.GetWebResponse(request, result) as HttpWebResponse;
          ThrowIfUnauthorized(response);
          return response;
       }
       private void ThrowIfUnauthorized(HttpWebResponse response)
       {
          // There are cases where response can be null (dropped network connection is one).
          if (response != null && response.StatusCode == HttpStatusCode.Unauthorized)
          {
             throw new UnauthorizedException(response);
          }
       }
       internal SomeObject m_state;
    }
    public class UnauthorizedException : ApplicationException
    {
       public UnauthorizedException(HttpWebResponse response)
       {
          m_response = response;
       }
       internal HttpWebResponse m_response;
    }
  • Buck Hodges

    More on working with SOAP proxies

    • 3 Comments

    In my last post on authentication and SOAP proxies, I mentioned setting the Credentials property on the wsdl.exe-generated proxy object.  Another way to do it and do other things is to override the GetWebRequest() method.

    In the following example, the culture is set in the standard HTTP header to tell the server what culture to use for any formatted data, and the credentials are set directly from some object in the app that holds the credentials.  The advantage of setting the credentials this way is that we don't have to know whether the credentials have changed -- we always get them from the main location before sending each SOAP request.

    internal class MyProxy : WsdlExeGeneratedProxy
    {
        // Customize the web request.
        protected override WebRequest GetWebRequest(Uri uri)
        {
            HttpWebRequest request = base.GetWebRequest(uri) as HttpWebRequest;
            request.Headers.Add("accept-language", CultureInfo.CurrentUICulture.Name);
            request.Credentials = m_state.Credentials;
            return request;
        }
     
        internal SomeObject m_state;
    }

    If you are using Whidbey Beta 1, check out the article on MSDN about the new SOAP proxy generation options, including generating the proxy assembly at build time (rather than the default of generating and building an assembly at runtime) and how to turn on compression.

  • Buck Hodges

    So what runs on Virtual PC 2004?

    • 0 Comments
    I was reading an article comparing Virtual PC 2004 and VMWare 4.5, and they mentioned a link to a site called “What Works and What Doesn't in Microsoft Virtual PC 2004.”  The site currently lists 622 entries.
  • Buck Hodges

    Another Hatteras blogger: Jim Presto

    • 0 Comments
    Jim Presto, a tester on the Hatteras team, has got a blog going.  He starts off with checkin and promises to delve into checkin policies next.  Now, he mentions that “hopefully everyone has the concept of a portfolio project,” but I'm not sure about that.  Perhaps James will post some more about that and how it relates to Hatteras.
  • Buck Hodges

    Using pushd to get to network paths

    • 2 Comments

    A short while ago I saw someone at the office use pushd to cd into a network path.  I've used pushd/popd on Windows for some time, but I never thought to try it on a network path or actually read the help for it.  Pushd will actually map the path to a drive letter automatically and then take you there.  The latter part is expected, but mapping the drive is really cool.  Maybe it should be obvious (how else would the command line do it?), but it wasn't to me.  It's a lot more convenient than “net use“ or anything else that I know of.

    C:\>pushd /?
    Stores the current directory for use by the POPD command, then
    changes to the specified directory.
    PUSHD [path | ..]
      path        Specifies the directory to make the current directory.
    If Command Extensions are enabled the PUSHD command accepts
    network paths in addition to the normal drive letter and path.
    If a network path is specified, PUSHD will create a temporary
    drive letter that points to that specified network resource and
    then change the current drive and directory, using the newly
    defined drive letter.  Temporary drive letters are allocated from
    Z: on down, using the first unused drive letter found.
    
  • Buck Hodges

    Python on .NET just got more support

    • 0 Comments
    Jim Hugunin, who has been writing IronPython, has been hired by Jason Zander (CLR PUM).  He joins the CLR team on Monday, August 2, to work full time on IronPython and generally supporting dynamic/scripting languages on the CLR.  That's really great news for Python on .NET.  Check out the slide from his presentation at OSCON (July 28, 2004).
  • Buck Hodges

    Authentication and SOAP proxies

    • 2 Comments

    My last post discussed authentication in web service calls using HttpWebRequest.  That caused one reader to wonder how this ties back to SOAP requests.

    If you are using wsdl.exe to generate a SOAP proxy class, it derives from System.Web.Services.Protocols.SoapHttpClientProtocol.  That class has a Credentials property. If you want to use the currently logged-in user's credentials, you would assign CredentialCache.DefaultCredentials to the Credentials property.  The same comment about having to assign an instance of NetworkCredential or CredentialCache apply as the proxy uses the HttpWebRequest class.

    [Updated 8/05/2004]  Check out the article on MSDN about the new SOAP proxy generation support in Whidbey Beta 1, including generating the proxy assembly at build time and how to turn on compression.

  • Buck Hodges

    Authentication in web services with HttpWebRequest

    • 20 Comments

    Hatteras has three tiers: client, middle, and data.  The middle tier is an ASP.NET web service on a Windows 2003 Server running IIS 6.  When the client (we use C# for both it and the middle tier) connects to the middle tier, it must authenticate with IIS 6.  Depending upon the IIS configuration, that may be negotiate, NTLM, Kerberos, basic, or digest authentication.  Here's a page on Internet Authentication in .NET.

    NOTE:  The code below uses the .NET 2.0 framework (Visual Studio 2005).

    In order to authenticate, the client must have credentials that the server recognizes as valid.  For Windows Integrated Authentication (comprising NTLM and Kerberos) using the current logged-on user, the client can use CredentialCache.DefaultCredentials.  Here's how it looks in code.

    using System;
    using System.IO;
    using System.Net;
    
    class Creds
    {
        public static void Main(string[] args)
        {
            Uri uri = new Uri(args[0]);
    
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
            req.Credentials = CredentialCache.DefaultCredentials;
    
            // Get the response.
            using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
            {
                StreamReader sr = new StreamReader(res.GetResponseStream());
                Console.WriteLine(sr.ReadToEnd());
            }
        }
    }

    You can find that same type of sample code in MSDN.  However, it gets more interesting if you want to use basic or digest authentication or use credentials other than the current logged-on user.

    One interesting fact is that the HttpWebRequest.Credentials property is of type ICredentials, but it only uses instances of NetworkCredential and CredentialCache.  If you implement ICredentials on your own class that is not one of those two classes, you can assign it to the Credentials property, but HttpWebRequest will silently ignore it.

    To go further, we need to look at the CredentialCache class itself.  This class is used to hold a set of credentials that are associated with hosts and authentication types.  It has two static properties, one of which we used above, that are the "authentication credentials for the current security context in which the application is running," which means the logged-on user in our case.

    The difference is very subtle.  The documentation for DefaultCredentials says, "The ICredentials instance returned by DefaultCredentials cannot be used to view the user name, password, or domain of the current security context."  The instance returned by DefaultNetworkCredentials, being new in .NET 2.0 and of type NetworkCredential, would presumably let you get the user name and domain, but it didn't work for me when I tried it with the following code (UserName returned an empty string).

    Console.WriteLine("User name: " + CredentialCache.DefaultNetworkCredentials.UserName);

    The NetworkCredential class implements both the ICredentials (NetworkCredential GetCredential(Uri uri, String authType)) and ICredentialsByHost (NetworkCredential GetCredential(String host, int port, String authType)) interfaces.  The ICredentialsByHost interface is new in .NET 2.0.

    The CredentialCache class has methods that let you add, get, and remove credentials for particular hosts and authentication types.  Using this class, we can manually construct what setting req.Credentials = CredentialCache.DefaultCredentials accomplished in the original example.

            CredentialCache credCache = new CredentialCache();
            credCache.Add(new Uri("http://localhost"), "Negotiate",
                          CredentialCache.DefaultNetworkCredentials);
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
            req.Credentials = credCache;

    The authentication type can also be explicitly specified as "NTLM" and "Kerberos" in separate calls to Add().  This page on authentication schemes explains using Negotiate as follows.

    Negotiates with the client to determine the authentication scheme. If both client and server support Kerberos, it is used; otherwise NTLM is used.

    Let's say you want to work with basic or digest authentication.  The documentation for CredentialsCache.DefaultCredentials and CredentialsCache.DefaultNetworkCredential says that neither will work with basic or digest.  If we add basic to credentials cache, we get a runtime exception.

            credCache.Add(new Uri("http://localhost"), "Basic",
                          CredentialCache.DefaultNetworkCredentials);

    The exception is thrown by the Add() method.

    Unhandled Exception: System.ArgumentException: Default credentials cannot be supplied for the Basic authentication scheme.
    Parameter name: authType
    at System.Net.CredentialCache.Add(Uri uriPrefix, String authType, NetworkCredential cred)

    So, in order to use basic or digest, we must create a NetworkCredential object, which is also what we need to do in order to authenticate as some identity other than the logged-on user.  To do that, we create NetworkCredential object and add it to the CredentialCache as follows.

            credCache.Add(new Uri("http://localhost"), "Basic" /* or "Digest" */,
                          new NetworkCredential("me", "foo", "DOMAIN"));

    Basic authentication sends the password across the wire in plain text.  That's okay for a secure connection, such as one using SSL, and for situations where you don't need much security.  Digest authentication hashes the password along with other data from the server before sending a response over the wire.  It's a significant step up from basic.

    Now we need to have the user name and password to create the NetworkCredential object.  There are two parts to this.  First is prompting the user for the name and password.  The second is storing the information.  For prompting there is the Windows dialog that pops up any time you go to a web site that requires authentication.  That dialog includes a "Remember my password" checkbox.  I don't yet know what the managed API is for that.

    To store and retrieve the information, there is the new managed DPAPI explained by Shawn Farkas in several blog postings.

    [Update 3:44pm]  The Windows dialog used when IE prompts for name and password is created by the CredUIPromptForCredentials() function.  CredUIConfirmCredentials() is used to save credentials that authenticated successfully, if desired.  Duncan Mackenzie's MSDN article Using Credential Management in Windows XP and Windows Server 2003 explains how to use it from .NET.

    [UPDATE 4/10/2006]  I updated the MSDN links that were broken.

  • Buck Hodges

    The story on why Team System is not in Beta 1

    • 2 Comments

    Someone on the newsgroups asked for an official answer on why Team System is not in Whidbey Beta 1.  The short answer is that it's not beta quality, so it didn't belong in a beta.  Keep your eyes open for another CTP release in the next few months.  The current plans for this upcoming CTP are for it to include the server portions of Team System that were not in the May release.

    Rick LaPlante personally replied to the post with the following answer.

    While Paul provides a skeptical, yet possible explanation, as I made the decision, I'll tell you what the real logic was. 

    CTPs (community technology previews) are about getting bits out regularly to customers for early feedback and discussion.  With this release of VS, we are trying to be more open about what we are building and give earlier access to folks to the bits.  By definition, these bits are basically stable builds from our own source trees with minimal additional quality checks built into the process.  They are <NOT> beta quality.  they are interim builds.  As such, it was appropriate to put parts of the Team System into the CTP because we met the quality bar and certainly needed to start getting feedback asap about the feature set and implementation.  As Paul correctly points out (and we've said many times) the Team System is not currently at beta quality and as such we did not include it in Beta 1 of VS.  We will have another CTP in the next few months based on the VS Beta 1 bits that will include the Team System (again not a beta quality build, but expected to be much better than the May CTP) and then follow on with VS Beta 2 which will contain a full, beta quality version of the Team System.

    Hope this answers your question.
    -Rick

  • Buck Hodges

    May CTP to appear again

    • 2 Comments

    The May 2004 CTP that contained Team System (but not Team Foundation, which includes source control and work item tracking) is supposed to be up on MSDN by Monday.  There were a number of requests for it in the newsgroups after it was mistakenly removed from MSDN.

Page 22 of 23 (570 items) «1920212223