On my work machine, I currently have VC 2003,2005,2008, and 2010 installed. Which one should the CPP/H file open in?
The right answer is obviously : whichever one is currently running.
And of course there's no way to do that.
Almost every day recently I've had a moment where I am working away in VC ver. A , and I double click some CPP file, and it doesn't pop up, and I'm like "WTF", and then I hear my disk grinding, and I'm like "oh nooes!" , and then the splash box pops up announcing VC ver. B ; thanks a lot guys, I'm really glad you started a new instance of your gargantuan hog of a program so that I could view one file.
Actually if I don't have a DevStudio currently running, then I'd like CPP/H to just open in notepad. Maybe I have to write my own tool to open CPP/H files. But even setting the file associations to point at my own tool is a nightmare. Maybe I have to write my own tool to set file associations. Grumble.
(for the record : I have 2008 for Xenon, 2005 is where I do most of my work, I keep 2003 to be able to build some old code that I haven't ported to 2005 templates yet, and 2010 to check it out for the future).
19 comments:
Can't you just associate c and h to a batch 4dos batch file that looks for the MSVC that's running?
4dos can look for an MSVC?
Easier. Why not to create a batch file for each VS you are using, that will modify the register to change file association for the one its going about to run, like
vs08.bat
-> associate cpp,hpp with vs08
-> run vs08
vs10.bat
-> associate cpp,hpp with vs10
-> run vs10
should be quite simple
That's a pretty good idea. How do I do :
-> associate cpp,hpp with vs08
?
You can use "assoc" to change file associations from the command line.
I don't have VisualStudio on this machine to check the exact syntax but running "assoc .cpp" will show you the current association. Just changing the version number is usually enough ...
Try ASSOC and FTYPE. Looks like ASSOC maps extension to type, and FTYPE maps type to application. I guess you could create one type for each version of VS, then use ASSOC to change the mapping.
A quick google suggests http://ss64.com/nt/assoc.html has some info...
BTW Here's what my PC says for .cpp:
[0][ C:\bin\4nt ]assoc .cpp
.cpp=VisualStudio.cpp.8.0
[0][ C:\bin\4nt ]ftype VisualStudio.cpp.8.0
VisualStudio.cpp.8.0="C:\vs2005\Common7\IDE\devenv.exe" /dde
Goddamnit, blogger ate my first post with my second one. My first post was basically "see ASSOC and FTYPE, the mapping is 2-step, oh and here's a link: http://ss64.com/nt/assoc.html".
Whoah , I had no idea assoc & ftype existed. Awesome.
Woah, assoc and ftype. That is awesome!
That doesn't support the default "open in notepad" though. That same problem has been pissing me off for a while, so I wrote a little app which reroutes file opens-
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <string>
// Forward declarations:
BOOL ListProcessModules( DWORD dwPID, const char* filename );
BOOL ListProcessThreads(const char* filename);
void main( int argc, const char** argv )
{
if (argc != 2)
{
printf("usage: %s [filename]\n", argv[0]);
return;
}
if (!ListProcessThreads(argv[1]))
{
std::string path;
path += "start notepad ";
path += argv[1];
system(path.c_str());
}
}
BOOL ListProcessModules( DWORD dwPID, const char* filename )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return( TRUE );
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
return( TRUE );
}
// Now walk the module list of the process,
// and display information about each module
do
{
if (strstr(me32.szModule, "devenv.exe"))
{
std::string path = "start \"";
path += me32.szExePath;
path += "\" ";
path += filename;
printf(path.c_str());
system(path.c_str());
CloseHandle( hModuleSnap );
return FALSE;
}
} while( Module32Next( hModuleSnap, &me32 ) );
// Do not forget to clean up the snapshot object.
CloseHandle( hModuleSnap );
return( TRUE );
}
BOOL ListProcessThreads(const char* filename)
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( TRUE );
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32 );
// Retrieve information about the first thread,
// and exit if unsuccessful
if( !Thread32First( hThreadSnap, &te32 ) )
{
CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
return( TRUE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if (!ListProcessModules(te32.th32OwnerProcessID, filename))
return TRUE;
} while( Thread32Next(hThreadSnap, &te32 ) );
// Don't forget to clean up the snapshot object.
CloseHandle( hThreadSnap );
return( FALSE );
}
Well done sir, I just built it and it seems to work dandy.
Yeah the assoc/ftype thing is awesome but doesn't actually solve the problem in question.
I mean, say I run vs08.bat , then vs10.bat , then close my vs10, it's associated to the wrong thing. Buggy, fragile.
This version's a little bit quicker. I was finding it a little bit laggy when running through VM Ware on my laptop-
#include <tlhelp32.h>
#include <stdio.h>
#include <string>
#pragma comment(lib, "User32.lib")
// Forward declarations:
BOOL ListProcessModules( DWORD dwPID, const char* filename );
BOOL CALLBACK EnumWindowsProc(__in HWND hwnd, __in LPARAM lParam);
void main( int argc, const char** argv )
{
if (argc != 2)
{
printf("usage: %s [filename]\n", argv[0]);
return;
}
if (EnumWindows(&EnumWindowsProc, (LPARAM)argv[1]))
{
std::string path;
path += "start notepad ";
path += argv[1];
system(path.c_str());
}
}
BOOL ListProcessModules( DWORD dwPID, const char* filename )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return( TRUE );
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
return( TRUE );
}
// Now walk the module list of the process,
// and display information about each module
do
{
if (!strcmp(me32.szModule, "devenv.exe"))
{
std::string path = "start \"";
path += me32.szExePath;
path += "\" ";
path += filename;
printf(path.c_str());
system(path.c_str());
CloseHandle( hModuleSnap );
return FALSE;
}
} while( Module32Next( hModuleSnap, &me32 ) );
// Do not forget to clean up the snapshot object.
CloseHandle( hModuleSnap );
return( TRUE );
}
BOOL CALLBACK EnumWindowsProc(__in HWND hwnd, __in LPARAM lParam)
{
DWORD threadId;
GetWindowThreadProcessId(hwnd, &threadId);
const char* filename = (const char*)lParam;
return ListProcessModules(threadId, filename);
}
Why don't you just use TH32CS_SNAPPROCESS ?
I'm turning this into a more generic utility I'll call SendTo , which will look for any process name and send the file to it, and errorlevel return if not found, so you can then run the default from a batch file.
Well I guess you don't really need to enumerate all processes, just the ones with windows
In fact you only need to check the first module of each process too, as that is guaranteed to be the exe
" Well I guess you don't really need to enumerate all processes, just the ones with windows "
Yeah but the number of processes is like an order of magnitude smaller than the number of windows typically (a few hundred vs a few thousand)
sendto.cpp-
#include <Windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <string>
BOOL ListProcessModules( DWORD dwPID, const char* processName, const char* filename )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return( TRUE );
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
return( TRUE );
}
CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
if (strstr(processName, me32.szModule) == processName)
{
std::string path;
path += "start \"\" /B \"";
path += me32.szExePath;
path += "\" ";
path += processName + strlen(me32.szModule);
path += " \"";
path += filename;
path += "\"";
printf("%s\n", path.c_str());
system(path.c_str());
return FALSE;
}
return( TRUE );
}
BOOL ListProcessThreads(const char* processName, const char* filename)
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( TRUE );
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32 );
// Retrieve information about the first thread,
// and exit if unsuccessful
if( !Thread32First( hThreadSnap, &te32 ) )
{
CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
return( TRUE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if (!ListProcessModules(te32.th32OwnerProcessID, processName, filename))
return TRUE;
} while( Thread32Next(hThreadSnap, &te32 ) );
// Don't forget to clean up the snapshot object.
CloseHandle( hThreadSnap );
return( FALSE );
}
int main( int argc, const char** argv )
{
if (argc != 3)
{
printf("usage: %s [process name] [filename]\n", argv[0]);
return -1;
}
if (!ListProcessThreads(argv[1], argv[2]))
{
return 1;
}
return 0;
}
vcsendto.bat-
@echo off
"%~dp0sendto" "devenv.exe /Edit" %1
if ERRORLEVEL 1 start notepad %1
Post a Comment