Click here to Skip to main content
16,020,840 members
Articles / Desktop Programming / ATL
Article

Launch VNC Shell Extension

Rate me:
Please Sign up or sign in to vote.
4.36/5 (12 votes)
25 Apr 2004CPOL3 min read 99.6K   1.1K   47   12
Launch VNC from Network Neighbourhood

Introduction

Sample image

We use RealVNC to remote control PCs in our network, VNC is a great product, but without remembering computer names it can be tedious to find the computer in the Network Neighbourhood, then copy the computer name into the VNC connection screen, so I developed this Shell Extension.

What is VNC?

From RealVNC Site:

"VNC stands for Virtual Network Computing. It is remote control software which allows you to view and interact with one computer (the "server") using a simple program (the "viewer") on another computer anywhere on the Internet. The two computers don't even have to be the same type, so for example you can use VNC to view an office Linux machine on your Windows PC at home. VNC is freely and publicly available and is in widespread active use by millions throughout industry, academia and privately."

RealVNC can be downloaded here.

Creating the Extension

I would first like to thank Michael Dunn for all his great efforts, especially with the tutorial: The Complete Idiot's Guide to Writing Shell Extensions - Part I. I used it as a starting point for my extension.

I followed his steps to create his extension demo, then changed his initialization interface code to handle Network Resources, instead of File Names.

CFSTR_NETRESOURCES

This format identifier is used when transferring network resources, such as a domain or server. The data is an STGMEDIUM structure that contains a global memory object. The structure's hGlobal member points to a NRESARRAY structure. That structure's nr member indicates a NETRESOURCE structure whose lpRemoteName member contains a null-terminated string identifying the network resource.

We have to use the RegisterClipboardFormat API function, supplying CFSTR_NETRESOURCES as the parameter, to get the shell registered clipboard format for Network Resources. We can then extract the name of the item selected from the first NETRESOURCE structure in the nr member of the NRESARRAY structure.

We check the type of resource, as we are only interested in Servers. The dwDisplayType member contains the type of resource.

if(pNtary->nr[0].dwDisplayType == RESOURCEDISPLAYTYPE_SERVER)

The string members in the NETRESOURCE structure contain offsets instead of addresses!

So we get to the first name selected by casting the structure as a char pointer, then we add the offset to the pointer, then cast it to a WCHAR pointer.

WCHAR* pwchRemoteName = (WCHAR*)((char*)pNtary + 
    int(pNtary->nr[0].lpRemoteName)); 

We remove the \\ from the begining of the returned name, and store it in the m_szPCName member variable for use later.

STDMETHODIMP CVNCShell::Initialize(LPCITEMIDLIST pIDFolder, 
                                   IDataObject *pDataObj, 
                                   HKEY hRegKey) 
{
HRESULT hr;
 
  if (pDataObj) 
    { 
      STGMEDIUM   medium;
      FORMATETC   fe;
      fe.cfFormat = RegisterClipboardFormat(CFSTR_NETRESOURCES);
      fe.ptd = NULL;
      fe.dwAspect = DVASPECT_CONTENT;
      fe.lindex = -1;
      fe.tymed = TYMED_HGLOBAL;

      hr = pDataObj->GetData(&fe, &medium);
      if(SUCCEEDED(hr))
      {
        LPVOID lpv = GlobalLock(medium.hGlobal); 
        if (lpv)
        {
          LPNRESARRAY pNtary = (NRESARRAY*)lpv;

          m_bShowMenuItem = false; 
          
          if(pNtary->nr[0].dwDisplayType == RESOURCEDISPLAYTYPE_SERVER)
          {
             m_bShowMenuItem = true;

             // The string members in the structure 
             // contain offsets instead of addresses!
             WCHAR* pwchRemoteName =  (WCHAR*)((char*)pNtary +
                int(pNtary->nr[0].lpRemoteName)); 

             // Copy name, minus \\ at begining of name, to local variable
             lstrcpynW (m_szPCName, pwchRemoteName + 2, 
                   lstrlenW(pwchRemoteName) * sizeof(TCHAR));
          }
                
          GlobalUnlock(medium.hGlobal);
        }
        else
          hr = E_UNEXPECTED;
        
        ReleaseStgMedium(&medium);
      }
  }
  return hr;
}

I also changed his InvokeCommand Interface to replace the code that displays a MessageBox with code that executes the VNC program, this assumes the VNC program is installed in the fixed path supplied, in our case it is always installed there, we pass the m_szPCName member variable containing the PCs name we stored earlier.

ShellExecute (pCmdInfo->hwnd, _T("open"), 
    _T("C:\\Program Files\\RealVNC\\vncviewer.exe"),
    m_szPCName, NULL, SW_SHOWNORMAL);
            
return S_OK; 

Registering the shell extension

The Shell defines additional objects under HKEY_CLASSES_ROOT which can be extended in the same way as file types.

The only one we are interested in is the Network\Type\2 subkey:

HKEY_CLASSES_ROOT\Network\Type\2\ShellEx\ContextMenuHandlers\VNCShellExt

From MSDN:

"For Network\Type\# , "#" is a network provider type code in decimal. The network provider type code is the high word of a network type. The list of network types is given in the Winnetwk.h header file (WNNC_NET_* values)."

So I Changed the Registry Resource from text file to this:

NoRemove Network
{
  NoRemove Type
  {
    NoRemove 2
    {
      NoRemove ShellEx
      {
        NoRemove ContextMenuHandlers
        {
         ForceRemove VNCShellExt = s '{B9442EFE-9815-4046-B6FF-4F3606291D8E}'
        }
      }
    }
  }
}

That is all, This is my first attempt at an article, and I have only been programming in C++ for a very short time, please be nice :)

References

License

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


Written By
Web Developer
Australia Australia
I started programming in BASIC when I was 8 on an old Dick Smith VZ-200. The VZ-200 had a Z80A processor running at 3.58Mhz, and 6K of RAM!

I moved on to programming in C when I was 13 on an 8086 XT computer, which was my next computer. I wrote many little programs including Terminate and Stay Resident programs. I also wrote a great deal of code for manipulating the video memory directly for fast text updating.

I was taught Pascal in high school, and never really did much with it, I stuck to programming in C. After leaving school, I never really programmed anything until I worked for a local company, which no longer exists, I was thrown into the world of database programming.

I spent several months learning Microsoft Access and SQL, and my biggest project was a multi-user Point of Sale program that I developed in house on the customers site. The program took almost a year to complete single handed, it was developed in MS Access. The program replaced a very old UNIX based program that was causing them problems.

I currently work for a large local company, I was employed to do general IT&T support, but soon moved on to developing many in house applications, including a full Intranet site.

I taught myself C++ and use it to develop many of my applications, I also use Visual Basic 6.

Now using .NET to develop most apps.

Comments and Discussions

 
GeneralATL ambiguous symbol Pin
Sayron10-Jun-05 7:45
Sayron10-Jun-05 7:45 
AnswerRe: ATL ambiguous symbol Pin
David Gilson11-Dec-05 21:11
David Gilson11-Dec-05 21:11 
GeneralDoesn't compile - cannot build dll Pin
Mike Greene27-Apr-04 7:56
Mike Greene27-Apr-04 7:56 
GeneralRe: Doesn't compile - cannot build dll Pin
David Gilson30-Apr-04 23:27
David Gilson30-Apr-04 23:27 
GeneralRealVNC, UltraVNC and TigthVNC fullscreen extension Pin
Lars [Large] Werner16-Mar-04 22:52
professionalLars [Large] Werner16-Mar-04 22:52 
GeneralFind the location of vncviewer.exe Pin
poltrone10-Dec-03 7:23
poltrone10-Dec-03 7:23 
This extension would be more general, if it woulndn't hardcode the location of 'vncviewer.exe'. If VNC was propperly installed, it's possible to determine the location of the executable by looking at the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Classes\VncViewer.Config\Shell\open\command'. On my computer it says '"C:\Programme\COM\VNC\vncviewer.exe" -config "%1"'. So it would be easy to extract the executables path from thatSmile | :)
GeneralRe: Find the location of vncviewer.exe Pin
David Gilson10-Dec-03 11:48
David Gilson10-Dec-03 11:48 
GeneralRe: Find the location of vncviewer.exe Pin
poltrone10-Dec-03 21:54
poltrone10-Dec-03 21:54 
GeneralRe: Find the location of vncviewer.exe Pin
David Gilson11-Dec-03 11:39
David Gilson11-Dec-03 11:39 
GeneralSeems overkill Pin
funny thing5-Dec-03 2:02
funny thing5-Dec-03 2:02 
GeneralRe: Seems overkill Pin
MaxiGroovy5-Dec-03 3:51
MaxiGroovy5-Dec-03 3:51 
GeneralRe: Seems overkill Pin
John M. Drescher5-Dec-03 9:30
John M. Drescher5-Dec-03 9:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.