search loading ...

Google Analytics: how to see page views

Using Google Analytics is great, however, it seemed to be missing the most important feature: individual page view count.

Google Analytics does have individual page view count, its just not very intuitive how to find it.

  • Go to your Google Analytics page.
  • Select "Reporting" at the top.
  • Select "Behavior" at the left.
  • Expand "Site Speed".
  • Select "Page Timings".
  • At the lower half of the page, select "page views" in the 2nd column header.


Google Analytics

How to migrate from WordPress to Ghost

I finally got hosted on Ghost. The process was not as easy as I had anticipted. I made a lot of mistakes. So perhaps through my difficult learning experience I can offer some suggestions to make the migration much easier for you.

This article is intended to be an overview, to point you in the right direction for each step. It is not intended to be a complete walk through from start to finish. I think all of the steps are easy and intuitive enough for an intermediate WordPress user to figure out.

Read through the article first, and if something doesn't make sense or if you feel totally lost, then perhaps migrating to Ghost isn't such a good idea for you. Setting up Ghost is more difficult than WordPress, because Ghost does not include everything that WordPress does, so features like site search, user comments, analytics, etc, need to be installed manually by editing some html and/or javascript files.


  • Self-hosted WordPress. If your blog is hosted by WordPress ( then you need to install WordPress on a webserver, export your WordPress blog to an XML file, and import that file into your self-hosted WordPress installation.
  • An existing Ghost blog, self-hosted or Ghost(Pro).
  • You may need a Blogger account to use as an intermedite during the export from WordPress and import into Ghost step. This may not be required for you, just giving you a heads up.


  • If you have a custom domain and your WordPress blog is hosted by WoredPress (, then you first need to go into your WordPress dashboard, Store, and delete the custom domain. If you purchased the custom domain from WordPress, then I dont know what to tell you, you will have to contact WordPress through their support forum and ask them for advice. If you purchased the custom domain elsewhere, then you can delete it yourself in the dashboard store. All you are really doing is telling WordPress to relinquish DSN control of your custom domain. You should then go to wherever you purchased your custom domain from, and change the DNS to point to your Ghost blog's URL.
  • Do NOT change your Ghost settings to use the custom domain yet. If you do this you are screwed. DNS takes a few days to change. If you tell Ghost to use the custom domain, and the DNS hasn't been updated and propigated throughout the major DNS servers yet, then when you go to your Ghost blog it will redirect to the custom domain, which will go to WordPress.
  • FYI: it took DNS about 3 days to update and propigate for my custom domain. During that time it intermittently resolved to either my old WordPress blog or the new Ghost blog. Be careful!
  • If your WordPress blog uses dated permalinks, then go to your Ghost blog settings, and enable "Dated Permalinks". This is very important! If this setting does not match between WordPress and Ghost, then all your permalinks will be different in your Ghost blog, all the search engine results for the next few days will not work, and anyone whos bookmarked any pages on your site those bookmarks will not work.
  • If your blog is hosted by WordPress ( then export it to an XML file, and import that XML file into a self-hosted WordPress.
  • Go to your self-hosted WordPress blog and install the Ghost WordPress plugin.
  • Use the Ghost plugin to export all your WordPress blog content to an XML file.
  • Go to your-blog-url/ghost/debug for self-hosted Ghost, or for Ghost(Pro), and import the XML file. If you get an error, click the button to "delete all content", wait about 2 minutes, and then try again. I had to try it about 5 times before it worked.
  • If you cannot get the XML file imported into Ghost, create a Blogger account, and try importing it there. Then export from Blogger and try importing that file into Ghost. I did not have to do this, but from reading other guides it seems to be a common requirement.
  • If you want to keep your existing user comments, then I suggest you use Disqus. The process is simple, you import the same XML file previously exported from WordPress, the request gets queued, and after a few days (seriously, it took 3 days when I tried it) all your user comments will be imported. In order for the user comments to show up in your blog you will have to modify the theme. That is easy and outside the scope of this article.
  • If you want to start over and not keep any of your existing user comments, then I would suggest you use Moot. I think Moot is much better than Disqus, but it does not seem to have an import feature.
  • If you dont like Disqus or Moot, then your only realistic alternative is to use Google+ for user comments. There are some instructions here. Thanks William Chambers.
  • If you want search capability, then I highly recommend using Google custom search. Dont waste your time with either GhostHunter or Tapirus, they both suck. Google custom search is the way to go, and it is very easy to setup and use. Just sigup/login with your Google account, add your blog URL, and then click the button for "get code". You will need to modify your theme to include the code. The theme you use may prevent the search box from displaying properly. If the search box looks messed up (it will be obvious) then you need to modify the code slighlty to use a "CustomSearchControl" instead of the standard "SearchControl". More details are here.
  • If you want to use a custom domain, and everything is setup and working, and the custom domain no longer resolves to your WordPress URL, then go to your Ghost settings and change the custom domain to the disired URL. You must do this last! If the DNS hasn't been updated and propigated throughout the major DNS servers yet, and it still resolves to your old WordPress blog, then you can get effecively redirected out of your Ghost blog until the DNS gets updated and propigated throughout the major DNS servers.
  • Enjoy your new Ghost blog!

export · Disqus · Moot · Tapirus · GhostHunter · Google now using Google custom search

I've finally got a working search feature. I had to use Google custom search with a "CustomSearchControl". I tried Ghost Hunter and Tapirus and they both suck. Neither Ghost Hunter nor Tapirus would produce any useful search results. Ghost Hunter would produce maybe 1 or 2 resutls when there should have been 10 or more. Basically the same issue with Taprius, except Tapirus would duplicate the same search result over and over.

There is something in the css of my theme that is preventing Google custom search from displaying properly. I am not able to use the suggested code from Google. In order for the searchbox to display properly, I have to use a "CustomSearchControl" instead of the standard "SearchControl". And it still doesn't display 100% properly. Its not actually supposed to say "Powered by Google" and its not supposed to have a gray background.

There is still an issue with the results not displaying properly, but at least I am getting results. Thats more than I can say for Ghost Hunter or Tapirus.

I'll try to clean the search so its not so ugly.

If you want to add a Google custom search, just go here, login, and add your website.

In case your interested, this is the code that works:

<div id='cse' style='width: 100%; font-size:85%'>search loading ...</div>  
<script src='//' type='text/javascript'></script>  
<script type='text/javascript'>  
google.load('search', '1');  
google.setOnLoadCallback(function() {  
  var searchControl = new'your-id-goes-here');
}, true);
</script> now hosted on Ghost

I am in the process of migrating from WordPress to Ghost. This has been slightly more troublesome than I expected.

It took much longer than expected for the DNS change to actually take effect. It worked a few times and stopped working, this went back and forth for a few days, not sure why. It seems to be be working now.

I am still going through all the posts and fixing the code blocks. You may notice some HTML junk in the code blocks. I apologize for any inconvenience.

After careful consideration, I have decided to use Disqus as a commenting platform. I think Disqus sucks and I would much rather use Moot. The only reason I am choosing to use Disqus is because I wanted to keep all my existing comments from WordPress, and Disqus is the only commenting platform that I am aware of that has an import feature.

The search feature is currently using GhostHunter and it is working quite poorly. A lot of keywords produce no results even though the keyword exists in the post title. I will try to fix this asap.

If you like the old WordPress site better, you can still access it here:

scanf, printf with BYTE

  • There is a lot of misinformation out there about what scanf/printf format specifier to use with BYTE.
  • According to the Microsoft documentation (or lack thereof) there is no specific format string specifier that expects the matching parameter to be a pointer to an unsigned 8-bit integer.
  • I see a lot of suggestions to use %hhd with BYTE. It may work for non-Microsoft compilers which support the "hh" width specifier, but it will not work with Microsoft!
  • Microsoft compilers currently do not support the "hh" width specifier in any existing version of Visual Studio, so using %hhd or %hhu with BYTE does *NOT* work!

scanf-related functions:

  • With scanf-related functions, do not use %hhd or %hhu with BYTE otherwise you will get stack corruption.
  • If you use %hhu, the hh width specifier is ignored, so it will parse as 'u', which expects the matching parameter to be a pointer to a 32-bit unsigned integer. If the matching parameter is a BYTE, it will most likely be populated with the expected value, however, the next 3 bytes of data in memory will be stomped on.
Don't believe me? Test this yourself. If your curious about %hu its the same result. The memory of TryUint gets stomped on.
#pragma pack( 1 )
  struct ByteAndUint
    BYTE TryByte = 0;
    UINT TryUint = UINT_MAX;
#pragma pack()
  ByteAndUint Test;
  swscanf(L"123", L"%hhu", &Test.TryByte);
  ASSERT(Test.TryUint == UINT_MAX);
  • Solutions:
  • With scanf-related functions, use %d with a temporary int.
  • Or, use _wtoi(), _ttoi(), atoi() instead of sscanf.
Use scanf with temporary int (or UINT doesn't matter):
int Temp = 0;  
swscanf( L"123", L"%d", &Temp );  
BYTE Value = static_cast<BYTE>( Temp );  
// result: Value = 123
Use Xtoi() instead of scanf:
BYTE Value = static_cast<BYTE>(_wtoi(L"123"));  
// result: Value = 123

printf-related functions:

  • With printf-related functions, you can use %d or %u with BYTE. You can also use %hd or %hu with BYTE, however, the 'h' width specifier when used with printf-related functions doesn't actually do anything.
  • Download the PDB debugging symbols from Microsoft and step through it if you don't believe me. Adding the 'h' width specifier with sprintf doesn't actually do anything, it internally does set Flag |= FL_SHORT, but that Flag isn't used afterwards. With printf, %hd and %hu are the same as %d and %u.
  • Solutions:
  • With printf-related functions, use %d or %u.

Use printf with "%d" (or "%u" doesn't matter):

WCHAR Str[8] = {'\0'};  
BYTE Value = 123;  
swprintf(Str, L"%d", Value); // use %d or %u  
// result: Str = "123"

%d · %hd · %hhd · byte · c++ · C/C++ · char* · Format · MSDN Documentation Errors · printf · scanf · specifier · sprintf · sscanf · sscanf_s · ssprinf_s

Return-by-value vs pass-by-reference


  • This article is an attempt to explain a very common usage scenario of return-by-value where RVO is not applied (so the object is copied) and therefore is not as fast as it would be if you use pass-by-reference (which avoids the copy).
  • Please do not misinterpret the purpose of this article. If you think this article is just a case against using return-by-value, you are wrong.
  • This article exposes a dangerous assumption, apparently that a lot of programers make (including myself prior to writing this article), that RVO is applied to every usage scenario of return-by-value.
  • Return-by-value should not be avoided just because it might cause a copy. It is more important to learn which usage scenarios of return-by-value are "eligible" for RVO, and use that information effectively.

  • There are many arguments comparing use of return-by-value vs pass-by-reference.
  • If you use return-by-value, your code will be simple and more visually appealing, but there is a good chance that objects you return are copied unnecessarily. Also, error handling must be done through exception handling, unless you can reserve a specific return value for use as an error result.
  • If you use return-by-value, a copy may occur if "return value optimization" (aka RVO) is not applied (there are scenarios where RVO is not applied).
  • If you use pass-by-reference, you will have slightly more code (due to error checking of return values), the code will be uglier (due to having to create an object to pass as an in-out parameter), but you are pretty much guaranteed to avoid the unnecessary copying objects being passed in-out to-from functions.
  • Here is an excellent article on the subject: Don’t be Afraid of Returning by Value, Know the Return Value Optimization by Anders Schau Knatten (C++ on a Friday blog).
  • Anders suggests using return-by-value, and that return-by-value does not cause any unnecessary copying of objects, due to return value optimization.
  • However, I do have an issue with something he mentioned:

"...the conclusion is simple: Don’t be afraid of returning large objects by value! Your code will be simpler, and just as fast"

  • IMO, that is dangerous advice, because it is incorrect to assume that RVO is applied to all usage scenarios of return-by-value.
  • Anders is correct, in that return-by-value will be just as fast as pass-by-reference, but only if RVO is applied (and there are usage scenarios of return-by-value where RVO is not applied).

RVO not applied to getter functions for class members

  • I tried to think of a very common usage scenario of return by value, something that I use all the time, something that other programmers use all the time, that might not be eligible for RVO.
  • The scenario I came up with is using a "getter" function to return a class member variable. Thats about as common and simple as it gets! This is something that is used everywhere!!! In many scenarios, its used to return strings or other large objects!!!! Yikes!!!
  • I purposely chose this usage scenario because it explains the entire purpose of this article, a usage scenario of return-by-value where RVO is not applied.
  • The test I came up with is completely unrelated to Anders' test, so the numbers are not comparable in any way.
  • What my testing results show is that RVO is not always applied to return-by-value (which causes a copy), compared to pass-by-reference (which does not copy). Look at the output. See the return-by-value copies increase every time. Ouch!
  • In my opinion either technique will work acceptably well, however, there are scenarios where RVO is not applied, and it is incorrect to assume that RVO is always applied using return-by-value. If you absolutely must avoid a copy, and you cannot be bothered with checking to see if RVO will be applied in your usage scenario, then you should use pass-by-reference.
  • In scenarios where RVO is not applied, using pass by reference instead is faster. This may not actually translate to any noticeable performance increase. I am against micro-optimization. However, if you actually need optimized code (you probably don't), and you don't want to check every usage scenario to determine if RVO will be applied, then in my opinion using pass by reference is the way to go.
  • RVO is not applied in a class "getter" function, because the object being returned is a class member, so its scope will still exist after the function call, so it must be copied (its not going to be immediately destroyed).
  • If you dont believe me, or what to step through it yourself to see whats going on, here is the sample code which proves my theory:

File Test.h:

#pragma once
#include <Windows.h>
class CTest  
  CTest(const CTest&);

  int GetCtors() { return mCtors; }
  int GetCopies() { return mCopies; }
  void Reset();
  void PrintCopies( LPCTSTR vMessage );

  static int mCtors;
  static int mCopies;

File Test.cpp:

#include "stdafx.h"
#include "Test.h"

int CTest::mCtors = 0;  
int CTest::mCopies = 0;

// class CTest

CTest::CTest(const CTest&)  

void CTest::Reset()  
  mCtors = 0;
  mCopies = 0;

void CTest::PrintCopies( LPCTSTR vMessage )  
  wprintf( L"%s, ctors = %d, copies = %d\n", vMessage, GetCtors(), GetCopies() );

File TestContainer.h:

#pragma once
#include "Test.h"
class CTestContainer  
  CTest GetTest();
  void GetTest( CTest& vTest );
  void PrintCopies( LPCTSTR vMessage );
  void Reset();

  CTest mTest;

File TestContainer.cpp:

#include "stdafx.h"
#include "TestContainer.h"
CTest CTestContainer::GetTest()  
  return mTest;

void CTestContainer::GetTest( CTest& vTest )  
  vTest = mTest;

void CTestContainer::PrintCopies( LPCTSTR vMessage )  
  mTest.PrintCopies( vMessage );

void CTestContainer::Reset()  

File TheApp.cpp:

#include "stdafx.h"
#include "TestContainer.h"
#include "Test.h"
void PrintCopies1( LPCTSTR vMessage, CTest& vTest )  
  wprintf( L"%s, ctors = %d, copies = %d\n", vMessage, vTest.GetCtors(), vTest.GetCopies() );

int _tmain(int argc, _TCHAR* argv[])  
  // uses 1 ctor, 0 copy
  CTest test1;
  PrintCopies1( L"constructor", test1 );

  // uses 0 ctor, 1 copy
  CTest test2( test1 );
  test2.PrintCopies( L"copy constructor" );

  // each GetTest return-by-value uses 1 copy
  CTestContainer test3;
  int idx;
  PrintCopies1( L"return-by-value", test3.GetTest() );
  PrintCopies1( L"return-by-value", test3.GetTest() );
  PrintCopies1( L"return-by-value", test3.GetTest() );
  PrintCopies1( L"return-by-value", test3.GetTest() );
  PrintCopies1( L"return-by-value", test3.GetTest() );

  // each GetTest pass-by-reference uses 0 copy
  CTestContainer test4;
  CTest test5; // this causes an extra contructor
  test4.GetTest( test5 );
  test5.PrintCopies( L"pass-by-reference" );
  test4.GetTest( test5 );
  test5.PrintCopies( L"pass-by-reference" );
  test4.GetTest( test5 );
  test5.PrintCopies( L"pass-by-reference" );
  test4.GetTest( test5 );
  test5.PrintCopies( L"pass-by-reference" );
  test4.GetTest( test5 );
  test5.PrintCopies( L"pass-by-reference" );

#ifdef _DEBUG
  fgetc( stdin ); // pause
  return 0;


constructor, ctors = 1, copies = 0
copy constructor, ctors = 0, copies = 1
return-by-value, ctors = 1, copies = 1
return-by-value, ctors = 1, copies = 2
return-by-value, ctors = 1, copies = 3
return-by-value, ctors = 1, copies = 4
return-by-value, ctors = 1, copies = 5
pass-by-reference, ctors = 2, copies = 0
pass-by-reference, ctors = 2, copies = 0
pass-by-reference, ctors = 2, copies = 0
pass-by-reference, ctors = 2, copies = 0
pass-by-reference, ctors = 2, copies = 0

C/C++ · Compiler · constructor · copy · pass by reference · return by value · return value optimization · rvo

Using std::map with Windows CE causes error LNK2019: unresolved external symbol _Lockit

  • If you attempt to use std::map with Windows CE, you will get the following linker error:
error LNK2019: unresolved external symbol "public: __cdecl std::_Lockit::~_Lockit(void)" error LNK2019: unresolved external symbol "public: __cdecl std::_Lockit::_Lockit(void)"
  • The actual errors are a mile long, I have included just the beginning portions.
  • There are multiple suggested solutions out there, however, none of them worked for me, or I did not consider them an acceptable answer.
  • The best solution, in my opinion, is to search your PC for xlock.lib, add the location to your project's vc++ "lib" directories, and link it:
#pragma comment( lib, "xlock" )
  • I found 4 copies of this file on my PC. I tried the first location in the search results and it worked for me.

C/C++ · external · LNK2019 · lock · lockit · map · std · STL · stl · symbol · unresolved · wince · Windows CE · Windows CE 6 · _Lockit

Examine return values of function calls in Visual Studio 2010

  • There are two parts to examining return values of functions:
  • 1) Examining return values of functions.
  • -and-
  • 2) Examining return values of stacked function calls.

Examining return values of functions:

  • Examining return values of function calls is a no-brainer. Just show the "autos" window (Debug->Windows->Autos) and click step-over when the execution pointer is on a function call. The function's return value will be displayed in the autos window.
  • Return value inspection has been around since at least 1996 in Visual C++ 4.0. I never used Visual C++ 4.0, however, I do know the feature existed because return value inspection is covered in detail in NuMega's "Debugging 32-Bit Windows Applications" book, chapter 2, Using the Visual C++ 4.0 Integrated Debugger, which was published in 1996 and I own the book.
  • I'm just mentioning VC++ 4.0 as an example of how the a feature has been around a very long time.

Return value inspection of stacked function calls:

  • I'm talking about getting the return values when you do something like this:
  • int result = Multiply(FourTimes(Five()), Six());
  • That example is from the horribly written MSDN article Examine return values of method calls which is specifically for Visual Studio 2013. The example code in that article is useless. The screenshot shows incorrect values for the given code. If you actually run the code it will produce different results from the screenshot. The names of the functions (Five, Six, etc) do not match their return values. Don't even bother reading it, its a total waste.
  • The CodeProject article  8 great features in Visual Studio 2013 seems to indicate that return value inspection of stacked function calls is a new feature for Visual Studio 2013.
  • I'm not sure why that article, and there are some other blogs out there also, that act like return value inspection of stacked function calls is a few feature and Visual Studio 2013 is the first version to have it.
  • Visual Studio 2010's return value inspection works with stacked function calls.
  • Comparing Visual Studio 2010's output in the autos window to the "8 great features in Visual Studio 2013" article, the results are the same.
  • Test this yourself:
int Bar();  
void Foo( int p );

int _tmain(int argc, _TCHAR* argv[])  
 Foo( Bar() * Bar() ); // put a breakpoint here
 // click step-over

int Bar()  
 Sleep( 100 );
 return GetTickCount();

void Foo( int p )  
 TRACE( L"%d\n", p );
  • Insert a break-point on the line Foo( Bar() * Bar() );
  • Click step-over.
  • If you show the "autos" window (Debug->Windows->Autos), you will see something like this:
  • Bar returned 494619952 int
  • Bar returned 494620061 int
  • The actual values you see will be different, but the concept works.

auto · autos · function calls · MSDN Documentation Errors · nested · return values · stacked · Uncategorized · Visual Studio · Visual Studio 2010 · watch

How to change a project's source control from SourceSafe to TFS

  • This article does not cover how to migrate your SourceSafe database to TFS.
  • This article is intended to only describe how to migrate a project's source control from SourceSafe to TFS.
  • This article assumes you have already successfully migrated your SourceSafe database to TFS, the project's source control is currently SourceSafe, and you have a working TFS server or a working account (aka visual studio online).
  • FYI: hosts a TFS (team foundation as a service) that is free to use for up to 5 users. Very nice! Check it out.
  • I have wasted a lot of time trying to figure out how to properly migrate a project's source control from SourceSafe to TFS. I think I've finally figured it out.
  • Try to follow the steps exactly as listed, in the order listed. Its taken me many tries to get it working properly, so these steps are very thorough and I've tried my best to explain exactly what has worked for me. If you find a better way, please let me know so I can update this article.

1) Connect to team project (do once):

  • Launch Visual Studio.
  • Open the "Team Explorer" panel (View, Team Explorer).
  • If you have not already done so for another project, click the "Connect to Team Project" icon, and enter your TFS server url, username, password, and select the desired team project collection and root team project(s), then click Connect.

2) Set local mapping (do once):

  • Double-click "Source Control" within the desired project in the Team Explorer panel.
  • If you have not already done so for another project, right-click the topmost element in the sources tree, select "Set Mapping" and selected the desired local folder. Choose wisely, its a pain in the ass to change it later.

3) Get latest version:

  • Launch Visual Studio.
  • Open the "Team Explorer" panel (View, Team Explorer).
  • Double-click "Source Control" within the desired project in the Team Explorer panel. This will open the Source Control Explorer window.
  • Navigate to the desired project's path in the Source Control Explorer.
  • Right-click, select Get Latest Version.
  • Resolve any conflicts.
  • If you have a file named "mssccprj.scc" file in source control, right-click and select Delete.
  • Keep the Source Control Explorer window open, were not done with it yet.

4) Delete the local mssccprj.scc file:

  • Launch Windows Explorer.
  • Navigate to to the project's path.
  • Delete the "mssccprj.scc" file (if it exists).

5) Open the project/solution:

  • Open the project/solution in the Visual Studio.
  • Most likely you will be prompted to check out the project/solution files, click Check Out.
  • Dismiss any errors about the missing mssccprj.scc file.
  • Most likely you will get a message about incorrect source control bindings. Select the option to "temporarily work uncontrolled".

6) Set source control to TFS:

  • Go to Tools, Options, Source Control.
  • Change the source control plug-in to "Visual Studio Team Foundation Server".
  • You will most likely have to change this for every project, because Visual Studio will change this setting back to match the currently opened project, which is still Source Safe.
  • Save the changes: File-> Save All.

7) Change the project's source control bindings:

  • Go to File, Source Control, Change Source Control.
  • Select the first (solution) item and click Bind.
  • Select the second (project) item and click Bind.
  • Most likely you will be prompted to checkout the .vcxproj file, click Check Out.

8) Check in the project/solution files:

  • Go to File-> Save All.
  • Go to the Source Control window.
  • Right-click the project's folder and select "Check In Pending Changes".
  • You will be prompted with a list of files to update. Most likely the files in the list of files to include will be the .sln file, the .vcxproj file, and at least one .vssscc file.
  • Click "Check In" to commit the changes.
  • You're welcome!

change · migrate · project · source control · Source Safe · source safe online · sourcesafe · team foundation · Team Foundation Server (TFS) · TFS · Visual Studio ·

How to recursively purge deleted items in SourceSafe

  • Microsoft's KB article:  How to Reduce the Size of a Visual SourceSafe Database incorrectly says to use this command:
  • ss purge %/ -r (this will not work)
  • It also suggests using "VSSEMS" which seems to be non-existent. The link goes to the author's personal blog which no longer exists. Good luck finding a legit download.
  • Here are the correct instructions (use at your own risk):
  • Make a backup of your entire SourceSafe files. This is very important. The first time I tried the purge, it deleted all my files. I had to run the analyze tool multiple times before the purge worked properly.

1) Open a command prompt.

2) Change directory:

  • cd "program files (x86)microsoft visual sourcesafe"

3) Run the analyze tool:

  • analyze -F -V3 -D -C "path-to-srcsafe-ini-folder"
  • If you get any errors run it again.

4) Set SSDIR environment variable:

  • set SSDIR=path-to-srcsafe-ini-folder

5) Purge:

  • ss purge -r %/*
  • Enjoy!



deleted · MSDN Documentation Errors · purge · Source Safe · sourcesafe · vssems