Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Copy Address of File

4.80/5 (5 votes)
21 Apr 2012CPOL2 min read 27.6K   1.1K  
A very simple trick to assist you in eradicating out manual file name entries.

Introduction

Here in this tip, I'll show you adding into your Windows Explorer's context menu an option for copying the file address. Although most of us don't have any issue with manually copying the file address, but sometimes it is painful when the file name is more complex or you have to do this frequently.

Background

I remember the time when I had to put the file names (fully qualified) on command prompt. It took a long time and extra effort. It prompted me to design a very simple application that could have simply copied the address. I initially designed it in C# but would like to put forward the C version. However I would be posting both the codes( :) for C# fans).

Steps

We have got only a couple steps to achieve our objective.

  1. Setting the registry:

    To add to Windows explorer's context menu any option, it is required to add a key at HKEY_CLASSES_ROOT\*\shell. This will make the menu available for any file type. Thus our keys will be:

    HKEY_CLASSES_ROOT\*\shell\Copy Address and the command associated with it becomes: HKEY_CLASSES_ROOT\*\shell\Copy Address\command.

    Under the command key, only thing that needs to be set is data value, i.e., C:\Windows\CopyAddress.exe %1.

    Besides data, the name and type values will remain (Default) and REG_SZ respectively.

  2. Writing the code:

    It was simple till here and it's the last step, let's finish it off. As we can see in the registry value shown above " CopyAddress.exe %1 ", the %1 parameter will push the file address into the programs argument. We need to capture that address onto the clipboard for further usage. I'll show it in the next section how to write the handling code.

Using the Code

The code is not so big and just includes 4 to 5 WinAPI calls. And I'll better show the code first:

C++
#include <stdio.h>
#include <Windows.h>
#pragma comment(linker,"/SUBSYSTEM:WINDOWS") 

int _stdcall WinMain( HINSTANCE hInstance,
	HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	LPTSTR  lptstrCopy;
	HANDLE hglbCopy;
	if (!OpenClipboard(NULL)) 
		return MessageBoxA(0,"Operation Failed \r\n 
		Can't Open Clipboard ","Copy Error",MB_ICONERROR); 

	EmptyClipboard();
	
	hglbCopy= GlobalAlloc(GMEM_ZEROINIT | 
		GMEM_MOVEABLE,(lstrlen(lpCmdLine)+1)*sizeof(CHAR));
	if (hglbCopy == NULL) 
        { 
            CloseClipboard(); 
            return MessageBoxA(0,"Operation Failed \r\n 
            Unable to Allocate Memory ","Copy Error",MB_ICONERROR); 
        } 
	lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
	lstrcpyA(lptstrCopy,lpCmdLine);
	lptstrCopy[lstrlen(lpCmdLine)-1]=0; //To Remove Extra Space 
				//character supplied by registry in argument
	GlobalUnlock(hglbCopy);
	SetClipboardData(CF_TEXT, hglbCopy);
	CloseClipboard();	
	return 0;	
}

//Section 2
//Use this if #pragma comment(linker,"/SUBSYSTEM:CONSOLE")
//For all console POP Up lovers ;)   

int main(int argc,char* argv[])
{
	LPTSTR  lptstrCopy;
	HANDLE hglbCopy;
	
	int i=1;
	
	if (!OpenClipboard(NULL)) 
		return MessageBoxA(0,"Operation Failed ",
			"Copy Error",MB_ICONERROR); 

	EmptyClipboard();
	hglbCopy= GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,256*sizeof(char));
	if (hglbCopy == NULL) 
        { 
            CloseClipboard(); 
            return MessageBoxA(0,"Operation Failed ",
            	"Copy Error",MB_ICONERROR); 
        } 
	lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
	while(i<argc)
	{
		strcat(lptstrCopy,argv[i++]);
		if((i<argc)){strcat(lptstrCopy," ");}
	}

	GlobalUnlock(hglbCopy);
	SetClipboardData(CF_TEXT, hglbCopy);
	CloseClipboard(); 
	return 0;
}

I have given two codes one for CONSOLE SUBSYSTEM another for WINDOWS SUBSYSTEM. Explanation of the code:

To copy any data to clipboard, OpenClipboard must have been called. To delete the previous data, EmptyClipboard is required. To get a handle to the memory object, we will use GlobalAlloc and to use it in a pointer, GlobalLock is called. After that, nothing is a big deal, just copy into the string the command line parameter and set it to the clipboard using SetClipboardData function. CF_TEXT is the flag for text data.

The equivalent code in C# is shown below:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Copy
{
    class Program
    {   [STAThread]
        static void Main(string[] args)
        {              
            try
            {
                string Address = "";
                foreach (string ar in args)
                {
                    Address += ar+" ";                 
                }
                //MessageBox.Show(Address);
                Clipboard.SetText(Address);
            }
            catch { }
            Application.Exit();            
        }        
    }
}

I don't find things need to be explained in C#. ;) .They are self explaining, the only suggestion I'll give is to link it as Windows Application rather than Console Application and you'll avoid the pop ups.

Points of Interest

The most disappointing thing while coding with console was the array formation in the command line parameter because of the split character space. It ate an extra 30 min!! I'll be uploading the code files using this app!!!!!!!! ;)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)