Microsoft Visual SourceSafe OLE Automation

Ken Felder
Microsoft Corporation

October 1995

Contents

Introduction

The Visual SourceSafe Object Model

Visual SourceSafe Events (the IVSSEvents Interface)

Error Handling

Introduction

This specification describes the OLE Automation interfaces to Microsoft® Visual SourceSafe™ version 5.0. Future versions of Visual SourceSafe will attempt to make as few changes as possible to these interfaces. Versions earlier than Visual SourceSafe 5.0 do not support these interfaces in any way.

A Microsoft Visual Basic® application can get a Visual SourceSafe object and begin executing commands (such as "Get this file" or "Tell me whether this file is currently checked out"). It can also register itself to receive events from Visual SourceSafe. ("Let me know if someone checks this file out.") The two can be used together: for instance, if you programmatically tell Visual SourceSafe to check a file out, an event is triggered, letting Visual SourceSafe add-ins (and your own) know that the file is about to be checked out. Hence, the following code would cause a system hang by creating an endless loop of events.

Sub BeforeCheckout (File as VSSItem, Local as String)
File.Checkout
End Sub

Avoiding this kind of loop is the responsibility of the user and only requires a little common sense.

Hooking Up to Drive Visual SourceSafe

Finding a Visual SourceSafe object to drive is similar to  finding any other OLE object. A Visual Basic programmer  would:

Dim Database as new VSSDatabase 

and then call:

Database.Open 

A C++ programmer would:

CoCreateInstance 

the same object, and once again call the Open method.

The globally unique identifier (GUID) for the Visual SourceSafe database object, found in the file SSAPI.DLL, is 783CD4E2-9D54-11cf-B8EE-00608CC9A71F. You can view the GUID and other information in the .DLL by using the Object Browser in Visual Basic or the utility OLE2VW32.EXE (which comes with Microsoft Visual C++®).

Hooking Up to Receive Visual SourceSafe Events

To register for Visual SourceSafe events, add your tool to the user's registry so that Visual SourceSafe can CoCreateInstance your event handling object.

In addition, add yourself to the file SSADDIN.INI. You find this file by looking in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe\SCCServerPath, which will give the path to a file called SSSCC.DLL. SSADDIN.INI should live in that same directory. Then add a line containing <your ProgID>=1 to this file to register yourself as an add-in.

As an example, suppose that the registry variable were set to C:\VSS\WIN32\SSSCC.DLL. You would want a file called C:\VSS\WIN32\SSADDIN.INI. If that file did not exist, you would create it; if it did exist, you would open it. Then, supposing your programmatic identifier (ProgID) were "CoolAddIn," you would add the line "CoolAddIn=1" to the file. This would tell Visual SourceSafe to load your add-in based on a registry lookup on that ID.

Visual SourceSafe connects to your add-in via the standard connection point interfaces. The following is a brief overview of the system; see the OLE reference manuals for more detail.

  1. Visual SourceSafe finds your ProgID in SSADDIN.INI.

  2. Based on that, Visual SourceSafe calls CoCreateInstance on your ProgID to instantiate your object.

  3. Visual SourceSafe queries your object for an interface called IVSSEventHandler. Your object must support this interface which contains only one method: Init.

  4. Visual SourceSafe calls your Init method, passing in a pointer to an interface called IVSS on a Visual SourceSafe object.

  5. You then QueryInterface from IVSS to another interface on the same object, called IConnectionPointContainer. This interface supports a method called FindConnectionPoint.

  6. From that interface, you call FindConnectionPoint(IID_IVSSEvents), which returns an interface called IConnectionPoint.

  7. From that interface, you call the Advise method, passing a pointer to your own IVSSEvents interface.

  8. Visual SourceSafe is then hooked up and will start calling methods in your IVSSEvents interface.

A few notes about this process.

Other Technical Notes

A few miscellaneous, but important, remarks:

The Visual SourceSafe Object Model

The Visual SourceSafe object model, as seen in Figure 1, is very simple.

Figure 1. The Visual SourceSafe object model.

VSSDatabase A Visual SourceSafe database.
VSSItem A project or file. Note that there is also a VSSItems, which is a collection for all the children in one project.
VSSVersion One way of representing a specific version of a file or project. A VSSVersions is a collection of all the versions of a particular file or project.
VSSCheckout A checkout record on a file. Note that once again there is a collection, because one file may have many simultaneous checkouts.

The VSSDatabase Object and IVSSDatabase

The VSSDatabase object represents one Visual SourceSafe database, logged in as one user. It supports the IVSSDatabase interface, which contains the methods and properties described below.

This interface is very important because it is the starting point of a Visual SourceSafe session. You always start by calling the Open method to login, and then you get a VSSItem, which is the launching point for all Visual SourceSafe commands.

Database properties

HRESULT VSSItem ([in]BSTR Spec, [in,defaultvalue(0)]boolean bDeleted, (out,retval)IVSSItem **ppIVSSItem);
HRESULT SrcSafeIni ([out,retval]BSTR *pSrcSafeIni);
HRESULT DatabaseName ([out,retval]BSTR *pDatabaseName);
HRESULT UserName ([out,retval]BSTR *pUsername);
HRESULT CurrentProject ([out,retval]BSTR *pPrj);
HRESULT CurrentProject ([in]BSTR Prj);

Database methods

HRESULT Open ([in,defaultvalue(0)]BSTR SrcSafeIni, [in,defaultvalue(0)]BSTR Username, [in,defaultvalue(0)]BSTR Password);

This function is how you log into Visual SourceSafe. The first parameter specifies the path and name of a SRCSAFE.INI file to use and is therefore a way of choosing a Visual SourceSafe database. The other parameters specify a user name and password; if you do not specify them, Visual SourceSafe will find the user name from Windows or a user-defined environment variable, if possible. If the user cannot be logged in from this information, the call will fail.

If you do not pass in a SrcSafeIni parameter, Visual SourceSafe will attempt to find the SRCSAFE.INI file itself, using essentially the same algorithm that the Visual SourceSafe Explorer uses. This is a good thing to do if you just want to use whatever Visual SourceSafe database the user tends to work with; however, note that successive calls to Open may wind up in different databases! One safe way to work is to call Open with no SrcSafeIni variable and add your project to Visual SourceSafe, and then get and save the SrcSafeIni property. The next time you want to find that project again, call Open passing in that SrcSafeIni value, and you will be sure of opening the same database.

The VSSItem Object and IVSSItem

This object can represent either a file or project in Visual SourceSafe, or an old version of a file or project. It exposes the IVSSItem interface, which is where almost all Visual SourceSafe commands and queries are found. (Old versions are discussed in more detail later, in the section on versions.)

There are two primary ways to get an IVSSItem pointer. One is through a call to IVSSDatabase::VSSItem where you essentially make the very specific request: "give me an IVSSItem pointer for $/My/Web/FU.HTML." The other is through the VSSItems object, which is a collection of all the children of a project: "give me IVSSItem pointers for all the children of $/My/Web."

Item properties

HRESULT Spec ([out,retval]BSTR *pSpec);
HRESULT LocalSpec ([out,retval]BSTR *pLocal);
HRESULT LocalSpec ([in]BSTR Local);
HRESULT Name ([out,retval]BSTR *pName);
HRESULT Name ([in]BSTR Name);
HRESULT Parent ([out,retval]IVSSItem **ppIParent);
HRESULT Type ([out,retval]int *piType);
HRESULT Deleted ([out,retval]boolean *pbDeleted);
HRESULT Deleted ([in]boolean bDeleted);
HRESULT IsCheckedOut ([out,retval]long *piStatus);
HRESULT IsDifferent ([in,defaultvalue(0)]BSTR Local, [out,retval]boolean *pbDifferent);
HRESULT Binary ([out,retval]boolean *pbBinary);
HRESULT Binary ([in]boolean bBinary);
HRESULT VersionNumber ([out,retval]long *piVersion);

Collections that are retrieved as properties of an item

HRESULT Items ([in,defaultvalue(0)]boolean IncludeDeleted, [out,retval]IVSSItems **ppIItems);
HRESULT Checkouts ([out,retval]IVSSCheckouts **ppICheckouts);

Item methods

Note   Many of the methods described here have a parameter called iFlags. The usage of this parameter is described in detail after the list of methods.

HRESULT Add ([in]BSTR Local, [in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]long iFlags, [out,retval]IVSSItem **ppIItem);
HRESULT NewSubproject ([in]BSTR Name, [in,defaultvalue(0)]BSTR Comment, [out,retval]IVSSItem **ppIItem);
HRESULT Destroy ();
HRESULT Get ([in,out,defaultvalue(0)]BSTR *Local, [in,defaultvalue(0)]long iFlags);
HRESULT Checkout ([in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]BSTR Local, [in,defaultvalue(0)]long iFlags);
HRESULT Checkin ([in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]BSTR Local, [in,defaultvalue(0)] long iFlags);
HRESULT UndoCheckout ([in,defaultvalue(0)]BSTR Local, [in,defaultvalue(0)]long iFlags);
HRESULT Share ([in]IVSSItem *pIItem, [in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]long iFlags);
HRESULT Move ([in]IVSSItem *pINewParent);
HRESULT Label ([in]BSTR Label, [in,defaultvalue(0)]BSTR Comment);
HRESULT Version ([in,optional]VARIANT Version, [out,retval]IVSSItem **ppIItem);
HRESULT Versions ([in, defaultvalue(0)]long iFlags, [out,retval]IVSSVersions **ppIVersions);

The iFlags parameter

Each time there is an iFlags parameter, you can pass zero, which means "do all the default things, as specified by the system and/or the user's SS.INI file." The only time you actually pass any of the flags is when you want to explicitly override a particular behavior, to say "do this thing" or "don't do this thing."

As an example, for recursion, you can pass zero, meaning "either recurse or don't, depending on the user's settings." Or, you can pass VSSFLAG_RECURSNO, meaning "do not recurse, no matter what the user's settings are" or VSSFLAG_RECURSYES, meaning "do recurse, no matter what the user's settings are." In general, of course, the default (0) settings should be used unless there is some particular reason to override them.

These flags can be combined by using the Or operator in C++, or simply by adding them in Visual Basic or Visual C++. So you could pass (VSSFLAG_RECURSNO+VSSFLAG_USEROYES), explicitly setting those two settings, but leaving the others to their defaults. Of course, (VSSFLAG_RECURSNO+VSSFLAG_RECURSYES) is invalid.

The actual flags are described below.

VSSFLAG_USEROYES
VSSFLAG_USERONO

Indicate whether the read-only flag should be used and assumed in the user's local director

VSSFLAG_TIMENOW
VSSFLAG_TIMEMOD
VSSFLAG_TIMEUPD

Indicate what date/time stamp Visual SourceSafe should give the local file: the current time (default), the last modification time, or the last check-in time.

VSSFLAG_EOLCR
VSSFLAG_EOLLF
VSSFLAG_EOLCRLF

Indicate what end-of-line character should be used: carriage-return, line-feed, or carriage-return/line-feed.

VSSFLAG_REPREPLACE
VSSFLAG_REPSKIP
VSSFLAG_REPMERGE
VSSFLAG_REPASK

Indicate what to do if a Get would replace an existing writable file on the user's local drive: replace the file, skip the file, or merge into the file. REPASK means that Visual SourceSafe calls your error handling callback function to find out whether it should replace the file or not.

VSSFLAG_CMPFULL
VSSFLAG_CMPCHECKSUM
VSSFLAG_CMPTIME

Indicate how Visual SourceSafe should determine if a file is out of date. When you Get a file, Visual SourceSafe does not physically copy it over if you already have the correct file. By default, a checksum is used for this comparison.

VSSFLAG_RECURSNO
VSSFLAG_RECURSYES

Indicate whether a command should be recursive, that is, whether it should act on an entire project tree.

VSSFLAG_FORCEDIRNO
VSSFLAG_FORCEDIRYES

When Visual SourceSafe recursively gets a project tree, it can put each subproject into its own working directory (FORCEDIRYES), or create a directory tree, ignoring the working directories of subprojects (FORCEDIRNO).

VSSFLAG_KEEPYES
VSSFLAG_KEEPNO

Indicate whether Visual SourceSafe should keep the file checked out after adding or checking it in.

VSSFLAG_DELYES
VSSFLAG_DELNO
VSSFLAG_DELNOREPLACE

Indicate whether the local file should be deleted after an Add, Checkin, or Undocheckout. The third value—replace the local copy with the Visual SourceSafe copy—is valid only on Undocheckout, where it is the default behavior in general.

VSSFLAG_BINBINARY
VSSFLAG_BINTEXT

Indicate whether a file is text or binary. If neither flag is passed, Visual SourceSafe automatically detects the file type at add-time.

VSSFLAG_DELTAYES
VSSFLAG_DELTANO

Indicate whether the file being added to Visual SourceSafe will store old versions of itself (Deltas) or not.

VSSFLAG_UPDUPDATE
VSSFLAG_UPDUNCH

Indicate whether a file being checked in that has not changed at all should be registered as a Checkin (creating a new version), or an Undocheckout. UPDASK means that Visual SourceSafe calls your error handling callback function to find out whether it should check the file in or not.

VSSFLAG_GETYES
VSSFLAG_GETNO

Indicate whether the file should be retrieved (gotten) on commands that do an automatic Get, such as Checkout and Share.

VSSFLAG_CHKEXCLUSIVE

Indicates whether a checkout should be exclusive. If you do not set this flag, the Checkout may be exclusive anyway due to the administrator's setting or the file type. But if you do set this flag, the Checkout will always be exclusive.

VSSFLAG_HISTIGNOREFILES

This flag is used in only one place—when you retrieve the Versions property of a project. The flag corresponds to the Ignore file checkins in the Visual SourceSafe Explorer project History dialog box, but in reverse. That is, if you do not set this flag, the History returns all the events in the life of the project and all its files. If you do set this flag, file histories are not scanned. Thus, you see only events in the life of the project (such as labels, file adds and deletes, and so on), and iterating through all the versions is much faster.

The VSSItems Object and IVSSItems

When you want to iterate through all the children (files and subprojects) in a project, you get a VSSItems from that project. The VSSItems object is a collection of all the children of that project. It supports the standard properties and methods of a collection object.

IVSSItems properties

HRESULT Count ([out,retval]long *piCount);

IVSSItems methods

HRESULT Item ([in]VARIANT sItem, [out,retval]IVSSItem **ppIItem);
HRESULT _NewEnum ([out,retval]IUnknown **ppIEnum);

Digression About Handling Versions

Before diving into the details of the VSSVersion object, it is worthwhile to discuss how versions are treated in general in Visual SourceSafe OLE Automation.

Two different objects to represent an old version

A specific old version of a file is represented by two different objects: a VSSItem and a VSSVersion. These two objects give you different abilities.

This article has primarily discussed VSSItems that represent a file in general (with no reference to version): for instance, $/A/FU.HTML. However, a VSSItem can also be used to represent a specific version of a file: for instance, $/A/FU.HTML version 2. In both cases, the VSSItem gives you general properties of the object (such as its name) and methods (such as Get). So if you call Get on a VSSItem that represents $/A/FU.HTML in general, you get the latest version; but if you call Get on a VSSItem that specifically represents version 2 of that file, you get version 2. You should note that some methods and properties of the IVSSItem interface are not valid when acting on an old version. For instance, if you have a VSSItem that represents version 2 of the file, you cannot set the Deleted property on that object, or call the Checkin method. Such actions are only valid on the file in general, not on a specific version.

The VSSVersion gives you version-specific properties of a specific version, such as the version number and the date/time associated with that change. One of the properties of a VSSVersion is the VSSItem associated with it. So, if you have a VSSVersion that represents version 2 of $/A/FU.HTML and you want to Get that version, you first find a VSSItem from the VSSVersion, and then call the Get method on that VSSItem. Note that you cannot go the other way! That is, there is no way—given a VSSItem that represents an old version—to retrieve a VSSVersion for that version.

As a final note, projects are treated in the exact same way as files. Hence, version 12 of $/A is also represented by both a VSSItem and a VSSVersion object.

How you get an old version

Suppose you have a VSSItem that represents the file $/A/FU.HTML in general (not version specific). How do you get objects that represent specific versions? There are two different ways.

The first is the Version property. You retrieve the Version property on your general VSSItem, passing in a version identification string (representing a date, version number, or label), and you receive back a VSSItem representing that particular version of the same file.

The second way is with the Versions property, which returns a VSSVersions collection on the general VSSItem. You iterate through that collection to list all the versions of the file or project. For each version that you receive, you can get properties to display or a VSSItem to act on.

Both of these methods are described in more detail later in this article

The VSSVersion Object and IVSSVersion

When you want to iterate through all the versions of a file or project, you use the Versions property of that file or project to get a VSSVersion object. You use that object to iterate through a series of VSSVersion objects, each of which has enough properties to display version information to the user. Using this object, therefore, you could create a display of the entire history of an object.

However, this object has no methods. If you want to Get an old version, you use the VSSItem property to get a VSSItem that represents that particular version, and then call the Get method on that item.

Version properties

HRESULT Username ([out,retval]BSTR *pUsername);
HRESULT VersionNumber ([out,retval]long *piVersion);
HRESULT Action ([out,retval]BSTR *pAction);
HRESULT Date ([out,retval]DATE *pDate);
HRESULT Comment ([out,retval]BSTR *pComment);
HRESULT Label ([out,retval]BSTR *pLabel);
HRESULT VSSItem ([out,retval]IVSSItem **ppIItem);

The VSSVersions Object and IVSSVersions

The VSSVersions object is a collection of all the versions of a given file or project. However, it is a very odd collection object in a number of ways.

The Count property and Item method are not implemented in this collection. The only way to use this collection is to call the _NewEnum method (in C++), or use a for-each loop (in Visual Basic).

You cannot have more than one Versions enumerator open at once. This means that the Clone method is not implemented on the Versions enumerator. More importantly, it means that if you want to get the recursive history of a project, you should allow Visual SourceSafe to do it for you (by using the VSSFLAG_RECURSYES flag on the Versions property when you first get the collection), rather than doing the recursion manually.

There is one further important note: not all the versions that you get are actually versions of the object you started with.

If you are doing a history of $/A/FU.HTML, most of the versions you see will refer to that particular file. However, some of the versions you see will be labels that were applied to the project (not to the file). If you get back the label "2.00b," and then get a VSSItem for that version, you may be getting an item that represents FU.HTML (if the label was applied to the file), or an item that represents $/A (if the label was applied to the project).

Similarly, if you are doing a history of $/A, you will see all the checkins of FU.HTML. So, once again, although you started with one thing (the project), some of your versions refer to a different thing (the file).

So, here is a wrong way to use this interface. You want to find FU.HTML as it was on 10/27/93. You get a Versions collection and work your way through it until the date reaches that point; then you get a VSSItem from that version and call the Get method. You may retrieve exactly what you wanted; or, you may be very surprised to discover that you have retrieved the entire project!

The right way to do that sort of operation is to use the Version method, not the collection. When you ask for the version of FU.HTML with a particular date or label, call Version on FU.HTML, passing in that date or label, and then call Get on that. The Version method, unlike the Versions collection, will always return a version of the item you started with.

IVSSVersions methods

HRESULT _NewEnum ([out,retval]IUnknown **ppIEnum);

Returns an enumerator (an IEnumVariant) that supports the standard Next, Skip, and Reset methods (but not Clone, since you can only have one such enumerator open at a time). This method is used explicitly by Visual C++ programmers; Visual Basic programmers do not call it directly, but use the for-each loop, which relies on the enumerator.

The VSSCheckout Object and IVSSCheckout

Each VSSCheckout on a file represents one checkout record for that file. Hence, if the file is checked out five times, you will iterate through five such records in the VSSCheckouts collection. Each record contains information about that particular checkout in the form of seven properties.

IVSSCheckout properties

HRESULT Username ([out,retval]BSTR *pUsername);
HRESULT Date ([out,retval]DATE *pDate);
HRESULT LocalSpec ([out,retval]BSTR *pLocal);
HRESULT Machine ([out,retval]BSTR *pMachine);
HRESULT Project ([out,retval]BSTR *pProject);
HRESULT Comment ([out,retval]BSTR *pComment);
HRESULT VersionNumber ([out,retval]long *piVersion);

The VSSCheckouts Object and IVSSCheckouts

When you want very basic checkout information for a file, use the IsCheckedOut property. But when you want details, get a VSSCheckouts collection and use it to iterate all the checkouts on that file. You should note that the collection may potentially contain no items (the file is not checked out), one item (the file is checked out), or many items (the file is checked out multiple times), and that merges will automatically be done on check in).

The VSSCheckouts supports the standard properties and methods of a collection object.

IVSSCheckouts properties

HRESULT Count ([out,retval]long *piCount);

IVSSCheckouts methods

HRESULT Item ([in]VARIANT sItem, [out,retval]IVSSCheckout **ppICheckout);

Retrieves one particular checkout record. The item may be specified in one of two ways: either by using an integer (which represents a one-based index into the collection) or by naming a user name (which returns the checkout record, if any, for that particular user).

HRESULT _NewEnum ([out,retval]IUnknown **ppIEnum);

Returns an enumerator (an IEnumVariant) that supports the standard Next, Skip, Reset, and Clone methods. This method is used explicitly by Visual C++ programmers; Visual Basic programmers do not call it directly, but use the for-each loop, which relies on the enumerator.

Visual SourceSafe Events (the IVSSEvents Interface)

The section Hooking Up to Receive Visual SourceSafe Events describes the steps you go through to register your add-in with Visual SourceSafe. When the process ends, Visual SourceSafe has found your IVSSEvents interface and is ready to start calling you.

Visual SourceSafe exposes events for a few basic commands to Visual SourceSafe add-ins. All commands described by events are taking place on an individual file, so if a user checks out a project, a separate event will be generated for each file in the project.

The Before event indicates that the user is about to take an action. It is your opportunity to prevent the command from occurring by setting the *pbContinue variable to FALSE (0). As a rule of thumb, you should use the Before event only for the purpose of possibly preventing the command. You should definitely not take any actions that assume the command will occur, because it is possible that another event after you will actually prevent the command.

The After event indicates that the user just took an action. This is when it is appropriate for your program to do things that should be synchronized with the user action.

Note that there is no way for your add-in to tell from where the command is coming. For instance, if you discover that a file is about to be added to Visual SourceSafe, it may be coming from the Visual SourceSafe Explorer, from an integrated development environment (IDE), or even from a Visual SourceSafe add-in using the OLE Automation interface—including your own program! However, it is definitely not coming from the Visual SourceSafe command line because the Visual SourceSafe command line (in version 5.0) does not send events. This unfortunately means that it is possible for a command to happen without your add-in ever getting notified.

HRESULT BeforeAdd ([in]IVSSItem *piPrj, [in]BSTR Local, [out,retval]boolean *pbContinue);

The specified file (Local) is about to be added to the Visual SourceSafe project piPrj.

HRESULT AfterAdd ([in]IVSSItem *pIItem, [in]BSTR Local);

A new file has been added to Visual SourceSafe. *piItem is a VSSItem pointer for the newly created file.

HRESULT BeforeCheckout ([in]IVSSItem *pIItem, [in] BSTR Local, [out,retval]boolean *pbContinue);

The specified Visual SourceSafe file is about to be checked out to the specified local file name.

HRESULT AfterCheckout ([in]IVSSItem *pIItem, [in] BSTR Local);

The specified Visual SourceSafe file has been checked out to the specified local file name.

HRESULT BeforeCheckin ([in]IVSSItem *pIItem, [in] BSTR Local, [out,retval]boolean *pbContinue);

The specified Visual SourceSafe file is about to be checked in from the specified local file name.

HRESULT AfterCheckin ([in]IVSSItem *pIItem, [in] BSTR Local);

The specified Visual SourceSafe file has been checked in from the specified local file name.

HRESULT BeforeUndoCheckout ([in]IVSSItem *pIItem, [in] BSTR Local, [out,retval]boolean *pbContinue);

The specified Visual SourceSafe file is about to be unchecked out with the specified local file name.

HRESULT AfterUndoCheckout ([in]IVSSItem *pIItem, [in] BSTR Local);

The specified Visual SourceSafe file has been unchecked out with the specified local file name.

HRESULT BeforeRename ([in]IVSSItem *piItem, [in]BSTR NewName, [out,retval]boolean *pbContinue);

The specified file or project (*piItem ) is about to be renamed to the specified new name.

HRESULT AfterRename ([in]IVSSItem *pIItem, [in]BSTR OldName);

The specified file or project (*piItem ) has been renamed from the specified old name.

HRESULT BeforeBranch ([in]IVSSItem *piItem, [out,retval]boolean *pbContinue);

The specified file is about to be branched.

HRESULT AfterBranch ([in]IVSSItem *pIItem);

The specified file has been branched.

HRESULT BeforeEvent ([in]long iEvent, [in]IVSSItem *piItem, [in]BSTR Str, [in]VARIANT var, [out,retval]boolean *pbContinue);
HRESULT AfterEvent ([in]long iEvent, [in]IVSSItem *piItem, [in]BSTR Str, [in]VARIANT var);

These two events are included as part of the interface definition to allow for some expansion in the future without redefining the interface. If future events are added to the IVSSEvents interface, it will be done by calling BeforeEvent and AfterEvent, with the iEvent parameter designating the specific event, *piItem the file or project, and Str and var filling in any additional information required for the particular event. As of the writing of this spec, no iEvent codes are defined and these events are not used.

Error Handling

There are two kinds of errors that can occur during the running of a Visual SourceSafe command: errors and yes/no questions. Because the Visual SourceSafe OLE Automation calls have no user interface component, neither of these can be directly shown to the user. Errors may be returned to the caller as indications that a function call failed. Questions are answered by default; your calling application never even knows the question happened.

Errors

When you get an HRESULT back from a Visual SourceSafe method, you can use the standard OLE FAILED macro on that HRESULT to see if it indicates a failure. FAILED will tell you if an error occurred that was so severe that it prevented the method from completing.

The following is a list of all the errors that may be returned by Visual SourceSafe OLE Automation. Please note that your application can call the OLE function GetErrorInfo to get an IErrorInfo pointer and use that standard interface to get more information about any returned errors (such as a string to display to the user and on-line help information to display more details). The strings given here are the U.S. English versions and are listed so that you know the meaning of the errors. If you want to display an error, you should always use GetErrorInfo rather than hard-coding these strings.

Numerical values for these errors are in a file called SSAUTERR.H.

Error Code English String
ESS_CORRUPT File %s may be corrupt.
ESS_DT_BADDATESTR Invalid date string: %s
ESS_DT_INVALID Invalid time or date string.
ESS_NOMORE_HANDLES Too many file handles open.
ESS_FILE_ACCESSDENIED Access to file %s denied.
ESS_FILE_BADDRIVE Invalid drive: %s
ESS_FILE_BADHANDLE Invalid handle.
ESS_FILE_BADNAME Invalid file name: %s
ESS_FILE_BADPARAM Invalid access code (bad parameter).
ESS_FILE_BADPATH Invalid DOS path: %s
ESS_FILE_CURRENTDIR Folder %s is in use.
ESS_FILE_DISKFULL Disk full.
ESS_FILE_EXISTS File %s already exists.
ESS_FILE_LOCKED File %s is locked.
ESS_FILE_NOTFOUND File %s not found.
ESS_FILE_READ Error reading from file.
ESS_FILE_SHARE File %s is already open.
ESS_FILE_TOOMANY Too many file handles open.
ESS_FILE_VOLNOTSAME Cannot rename to another volume.
ESS_FILE_WRITE Error writing to file.
ESS_INI_BADBOOL Initialization variable %s must be set to Yes or No.
ESS_INI_BADLINE Invalid syntax on line %d of file %s.
ESS_INI_BADNUMBER Initialization variable %s set to invalid number.
ESS_INI_BADPATH Initialization variable %s set to invalid path.
ESS_INI_BADVALUE Initialization variable %s set to invalid value.
ESS_INI_NOSUCHVAR Cannot find initialization variable %s.
ESS_INI_NUMRANGE Initialization variable %s must be between %d and %d
ESS_INI_TOO_MANY_ENV Too many SS.INI environment strings.
ESS_LOCK_TIMEOUT Timeout locking file: %s
ESS_MEM_NOMEMORY Out of memory.
ESS_NO_TWEAK_CHKDOUT You cannot modify the properties of a file that is checked out.
ESS_NOMERGE_BIN_NODELTA You cannot perform a merge on a binary file or a file that stores latest version only.
ESS_NOMULTI_BINARY Cannot check out %s. It is binary and is already checked out.
ESS_NOMULTI_NODELTA %s stores only the latest version and is already checked out.
ESS_OS_NOT_EXE Error executing: %s
ESS_SS_ADDPRJASSOCFILE %s is a Visual SourceSafe configuration file and cannot be added.
ESS_SS_ADMIN_LOCKOUT The Visual SourceSafe database has been locked by the Administrator.
ESS_SS_BADRENAME Unable to rename %s to %s.
ESS_SS_CANT_FIND_SSINI Cannot find SS.INI file for user %s.
ESS_SS_CHECKED_OUT File %s is currently checked out by %s.
ESS_SS_CHECKED_OUT_YOU You currently have file %s checked out.
ESS_SS_CHECKOUT_OLD Cannot check out an old version of a file.
ESS_SS_CHKOUT_USER File %s is currently checked out by %s.
ESS_SS_CONFLICTS An automatic merge has occurred and there are conflicts. \nEdit %s to resolve them.
ESS_SS_DEL_ROOT Cannot delete the root project.
ESS_SS_DEL_SHARED A deleted link to %s already exists.
ESS_SS_FILE_NOTFOUND File %s not found.
ESS_SS_HISTOPEN A history operation is already in progress.
ESS_SS_INSUFRIGHTS You do not have access rights to %s.
ESS_SS_LATERCHKEDOUT A more recent version is checked out.
ESS_SS_LOCALRW A writable copy of %s already exists.
ESS_SS_MOVE_CHANGENAME Move does not change the name of a project.
ESS_SS_MOVE_NOPARENT Project %s does not exist.
ESS_SS_MOVE_ROOT Cannot move the root project.
ESS_SS_MUST_USE_VERS Cannot roll back to the most recent version of %s.
ESS_SS_NOCOMMANCESTOR Files have no common ancestor.
ESS_SS_NOCONFLICTS2 %s has been merged with no conflicts.
ESS_SS_NODOLLAR File %s is invalid. Files may not begin with $.
ESS_SS_NOT_CHKEDOUT File %s is not checked out.
ESS_SS_NOT_SHARED File %s is not shared by any other projects.
ESS_SS_NOTSEPARATED Files are not branched.
ESS_SS_OPEN_LOGGIN Unable to open user login file %s.
ESS_SS_PATHTOOLONG Path %s too long.
ESS_SS_RENAME_MOVE Rename does not move an item to another project.
ESS_SS_RENAME_ROOT Cannot rename the root project.
ESS_SS_ROLLBACK_NOTOLD Cannot rollback to the most recent version of %s.
ESS_SS_SHARE_ANCESTOR A project cannot be shared under a descendant.
ESS_SS_SHARED File %s is already shared by this project.
ESS_SSPEC_SYNTAX Invalid Visual SourceSafe syntax: %s.
ESS_UM_BAD_CHAR Bad user name syntax: %s.
ESS_UM_BAD_PASSWORD Invalid password.
ESS_UM_BADVERSION Incompatible database version.
ESS_UM_DEL_ADMIN Cannot delete the Admin user.
ESS_UM_PERM_DENIED Permission denied.
ESS_UM_RENAME_ADMIN Can not rename the Admin user.
ESS_UM_TOO_LONG User name too long.
ESS_UM_USER_EXISTS User %s already exists.
ESS_UM_USER_NOT_FOUND User %s not found.
ESS_URL_BADPATH The URL for project %s was not set properly.
ESS_VS_CHECKED_OUT File %s checked out.
ESS_VS_CHILD_NOT_FOUND Subproject or file not found.
ESS_VS_COLLISION Collision accessing database, please try again.
ESS_VS_EXCLUSIVE_CHECKED_OUT File %s is exclusively checked out.
ESS_VS_ITEMEXISTS An item with the name %s already exists.
ESS_VS_LONGNAME %s is an invalid %s name.
ESS_VS_MOVE_CYCLE You can not move a project under itself.
ESS_VS_NO_DELTA File %s does not retain old versions of itself.
ESS_VS_NOT_CHECKED_OUT File %s cannot be checked into this project.
ESS_VS_NOT_FOUND File or project not found.
ESS_VS_PARENT_NOT_FOUND Parent not found.
ESS_VS_VERS_NOT_FOUND Version not found.
ESS_VS_WANT_FILE This command only works on files.
ESS_VS_WANT_PRJ This command only works on projects.
ESS_URL_BUFOVERFLOW A link in %s was ignored because it was longer than Visual SourceSafe can understand.
ESS_URL_CANTCHECKHTML An error occurred while trying to check hyperlinks for %s.
ESS_SS_ADDINFAILED Error loading Visual SourceSafe add-in: %s.
ESS_CANCEL  
ESS_LOADSTRING_FAILED Error loading resource string.

Questions

The following questions can occur during the invocation of a Visual SourceSafe method. These questions will be answered automatically as indicated—your application will never know they happened. They are listed here, not because you can do anything about them, but so that you know what to expect when you call Visual SourceSafe.

As an example, consider the following scenario: the user deletes the FU.CPP file in a project, and then attempts to re-add the same file (same name and same contents) to the same project. In the Visual SourceSafe Explorer, when the user attempts to add the file, he will be asked if he wants simply to recover the previously deleted file. When you call the Add method in the Visual SourceSafe OLE Automation, the answer to that question (the first one listed in the table below) is automatically yes; that is, the deleted file is recovered.

Question Answer
A deleted copy of this %s file already exists in this project.

Do you want to recover the existing file?

Yes
Folder %s not found. Create? Yes
Have any conflicts in %s been properly resolved? Yes
File %s is currently checked out by %s. Proceed anyway? Yes
File %s was checked out to folder %s. Proceed in %s? Yes
File %s is checked out to project %s, and you are in %s.

Proceed anyway?

Yes
File %s is currently checked out by %s. Delete anyway? Yes
You currently have file %s checked out. Delete anyway? Yes
An item named %s was already deleted from this project.

Purge the old item and delete this one now?

Yes
This version of %s already has a label. Overwrite? Yes
The label %s is already used. Remove the old label? Yes
%s has been merged with no conflicts. Check in now? Yes
Redo the automatic merge? Yes
Delete local file: %s? Yes
%s is already checked out. Continue? Yes
File %s has been destroyed, and cannot be rebuilt. Continue anyway? Yes
Project $%s has been destroyed and cannot be rebuilt.

Continue anyway?

Yes
$%s was moved out of this project and cannot be rebuilt.

Continue anyway?

Yes
%s has changed. Undo check out and lose changes? Yes
A deleted file of the same name already exists in this Visual SourceSafe project.

Do you want to recover the deleted file instead of adding your local %s?

No
%s is writable. Replace? No
%s is checked out. Replace? No