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.
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. ([email protected]) // 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*shellCopy Namecommand] @="CopyShellName.EXE %1" [HKEY_CLASSES_ROOTDirectoryshellCopy_Name] "EditFlags"=hex:01,00,00,00 @="Copy Name" [HKEY_CLASSES_ROOTDirectoryshellCopy_Namecommand] @="CopyShellName.EXE %1" < 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>END CopyShellName.reg--- */ // From https://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); }