Copy Folder/File Names Directly from Shell

Environment: NT 4.0 SP3, VC5

If you are used to the "Copy Key Name" feature of the Registry Editor, then you might have thought why such a feature is not there in the Explorer. This is a small program that gives you exactly that. It can be used as a "shell right mouse menu command" to copy the name of the command line file/folder to the clipboard.

It also gives you a very useful function to convert short path names (MSDOS 8.3 format) to long NT style names. With small modifications you can use the same to do the reverse converison also. This is something that I could not find anywhere else.

To use this cool application, some registry modifications are also necessary. These are described in detail in the source code.

The code uses STL and NO MFC.

Download source as a file 7K

Source code

///X///////////////////////X////////////////////X/////////////////////////////
// NAME:		CopyShellName.CPP
//
// SYNOPSIS:	Used as a "shell right mouse menu command" to copy the name of
//				the command line file to the clipboard.
// DESCRIPTION:	This is a simple a "window-less Windows" application which 
//				expects a file name (full path) as it's only command line. This
//				command line is converted to a long file name and is copied to 
//				the clipboard. Includes a useful function to convert short (8.3)
//				path names to long ones.
// BUGS:		There are a few limitations - this exe always expects a file 
//				name as input. It will not process path names longer than 
//				MAX_PATH characters. For shortcuts, the name of the actual file will be
//				returned, not the name of shortcut.
//
// REGISTRY:	Use the CopyShellName.reg (pasted below) file to make the right 
//				regisrty entries for this to work. The first entry sets up 
//				CopyShellName to appear for all files. The second one is needed 
//				for File Folders. 
//				In case of some file extensions, the "Copy Name" may become 
//				the default operation. U can detect this if a program startup 
//				cursor appears when u double click a file, and then nothing
//				happens. For example, if ".CPP" is affected, when u double click a
//				.cpp file, instead of the file getting opened in VC, u will see only a 
//				program starting up cursor (that of explorer spawning CopyShellName.exe)
//				Solution: Take explorer/view/options/filetypes//edit/
//				Select ur action, and use the SetDefault button to set it as default.
//
// INSTALLATION:Put the CopyShellName.exe to any folder in the system path. Create
//				a ".reg" file with the contents given below in "Registry Settings".
//				Execute this file to set the entries into the registry. 
//				If u want to build the source, make sure u create a "Win32 Application"
//				project.
// PLATFORM:	Developed & Tested only on NT4.0(SP3 without IE4)/VC5
//
// AUTHOR:		Kumara Das K.R. (das@nest.stpt.soft.net)
// COMPANY:		NeST, India (www.nestindia.com)
//
// NOTES:		This is my first pgm using STL, so if the STL code can be made 
//				more efficient, go ahead and do it.
//				Second, there could be better ways of doing the same thing with
//				Shell Extensions, but this works fine for me:-)
//				If u can improve upon this, dont forget to send me a copy.
///X///////////////////////X////////////////////X/////////////////////////////

// SYSTEM INCLUDES
//
#include 
#include 
#include 

// PROJECT INCLUDES
//

// LOCAL INCLUDES
//

/* Registry Settings
---BEGIN CopyShellName.reg <>

REGEDIT4

[HKEY_CLASSES_ROOT\*\shell\Copy Name\command]
@="CopyShellName.EXE %1"

[HKEY_CLASSES_ROOT\Directory\shell\Copy_Name]
"EditFlags"=hex:01,00,00,00
@="Copy Name"

[HKEY_CLASSES_ROOT\Directory\shell\Copy_Name\command]
@="CopyShellName.EXE %1"


<>END CopyShellName.reg---
*/

using namespace std ;

PSTR gszAppName = "Copy Shell Name";

//Fwd Declarations
string 
MakeLongPathName(const char * anyPath);

inline void
CopyTextToClipBoard(const char * pText);

int PASCAL WinMain (HANDLE hInstance,HANDLE hPrevInstance,LPSTR lpszCmdLine, int nCmdShow)
{
	try
	{
		//The lpszCmdLine has path name in 8.3 format. So change it and copy it to CB.
		CopyTextToClipBoard(MakeLongPathName(lpszCmdLine).c_str());
		//If u want to use UNICODE, use the GetCommandLine function instead of lpszCmdLine
	}
	catch(...)
	{
		MessageBox(NULL,"SORRY, there was an ERROR",gszAppName,MB_SETFOREGROUND);
	}
	return 0;//since we are not entering msg loop
}

//Now the helpers

string //returns the long format of file/folder name alone 
MakeLongName(string anyName)//accepts full path, can be long or short
{
	WIN32_FIND_DATA fd = {0};
	HANDLE hFind = FindFirstFile(anyName.c_str(),&fd);
	DWORD dw = GetLastError();
	if(INVALID_HANDLE_VALUE != hFind)
	{
		FindClose(hFind);
		return fd.cFileName;
		/*If u want to convert long names to short ones, 
		  u can return fd.cAlternateFileName */
	}
	else
	{
		//If it fails, separate the last file/folder name in the 
		//input string and return it.
		//This definitely happens when we have a UNC name, other cases
		//can also be handled decently this way.
		return anyName.c_str()+anyName.find_last_of('\\')+1;
	}
}

string //returns the complete pathname in long format
MakeLongPathName(const char * anyPath)//accepts both UNC and traditional paths, both long and short
{
	string sin = anyPath;
	string sout;
	/*Our funda function FindFirstFile will fail if path lenght is > MAX_PATH*/
	/*U can solve it by using FindFirstFileW */
	if(sin.length() > MAX_PATH) return "!! ERROR - Too Long Name !!";
	int nbslashPos = sin.find_last_of('\\');
	while( ("\\" != sin) && (sin.npos != nbslashPos) )
		//the first condition avoids an unnecessary MakeLongName for UNC names
	{
		string tmp = MakeLongName(sin);
		sin.erase(nbslashPos,sin.length()-nbslashPos);//remove the last part
		sout = "\\" + tmp + sout;//construct the long paths 
		nbslashPos = sin.find_last_of('\\');
	}
	return sin+sout;//sin will contain the drive letter or "\\" in the case of UNC
}


////////////////////////////////////////////////////////////////////
// SetText
// - Places text on the clipboard
// From CClipboard Class
// ----------------
// Written by David Terracino 
// From http://www.codeguru.com/clipboard/index.shtml
////////////////////////////////////////////////////////////////////
//
// Parameters:
//	lpszBuffer - pointer to a string where the text is to be put
//	hWnd       - window handle to be used by clipboard
//
// Return Values:
//	TRUE       - Text was successfully copied from clipboard
//	FALSE      - No text on the clipboard
//
////////////////////////////////////////////////////////////////////
int CClipboard_SetText (LPCSTR lpszBuffer, HWND hWnd)
{
	HGLOBAL hGlobal;		// Global memory handle
	LPSTR lpszData;			// Pointer to clipboard data
	unsigned long nSize;	// Size of clipboard data

	// First, open the clipboard. OpenClipboard() takes one
	// parameter, the handle of the window that will temporarily
	// be it's owner. If NULL is passed, the current process
	// is assumed. After opening, empty the clipboard so we
	// can put our text on it.
	OpenClipboard(hWnd);
	EmptyClipboard();

	// Get the size of the string in the buffer that was
	// passed into the function, so we know how much global
	// memory to allocate for the string.
	nSize = lstrlen(lpszBuffer);

	// Allocate the memory for the string.
	hGlobal = GlobalAlloc(GMEM_ZEROINIT, nSize+1);
	
	// If we got any error during the memory allocation,
	// we have been returned a NULL handle.
	if (hGlobal == NULL) return FALSE;

	// Now we have a global memory handle to the text
	// stored on the clipboard. We have to lock this global
	// handle so that we have access to it.
	lpszData = (LPSTR)GlobalLock(hGlobal);

	// Now, copy the text from the buffer into the allocated
	// global memory pointer.
/*	
DAS: I like strcpy:-)
	for (UINT i = 0; i < nSize + 1; ++i)
		*(lpszData + i) = *(lpszBuffer + i);
*/
	strcpy(lpszData,lpszBuffer);

	// Now, simply unlock the global memory pointer,
	// set the clipboard data type and pointer,
	// and close the clipboard.
	GlobalUnlock(hGlobal);
	SetClipboardData(CF_TEXT, hGlobal);
	CloseClipboard();

	return TRUE;
}

inline void
CopyTextToClipBoard(const char * pText)
{
	CClipboard_SetText(pText, NULL);
}




Comments

  • Idea: Combine this with /win32/ShowPath.shtml

    Posted by Legacy on 06/01/1999 12:00am

    Originally posted by: Patrick Frants

    1. Looks like this webpage gives a more robust way of obtaining
    the long filename.

    2. How about combining these two pieces of code? I don't
    have too much time myself...

    Patrick Frants

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • A help desk is critical to the operations of an IT services business. As a centralized intake location for technical issues, it allows for a responsive and timely solution to get clients and their staff back to business as usual. In addition to handling immediate IT issues, a help desk performs several proactive tasks to ensure clients' IT systems remain operational and downtime is minimized. Thus, utilizing a help desk and following best practices can improve the productivity, efficiency and satisfaction of …

  • Live Event Date: April 22, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Database professionals — whether developers or DBAs — can often save valuable time by learning to get the most from their new or existing productivity tools. Whether you're responsible for managing database projects, performing database health checks and reporting, analyzing code, or measuring software engineering metrics, it's likely you're not taking advantage of some of the lesser-known features of Toad from Dell. Attend this live …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds