Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Wednesday, December 11, 2013

Source files missing from project, but still there (Linking error)

Situation: Some .cpp and .h files shared between several Visual Studio Project files in different VS solutions (I know - bad practice, but it was not my idea and I could not change it) were being relocated to a separate directory beside the solution dir of the project I was working on. By unloading the project in VS, then manually editing the .vcxproj file, it was a simple task to search and replace string entries like:

     ClCompile Include="folder\
with
     ClCompile Include="($SolutionDir)..\folder 

Since the job involved much more reorganizing, and there was a lot of other files in the project as well, it was not unexpected that several referencing and linker errors occurred along the way. 

Symptom: In the end I was faced with a linker problem I was not able to get rid of. LNK2001 and LNK2019 errors were filling my screen. I diffed the old and the new .vcxproj files to search for what I had lost along the way, but found no apparent problem at first. Not until I closely examined what reference the linker could not find, making sure that both a header entry and an implementation body (usually in a corresponding .cpp file) were actually present in the project. Somehow some of the files were not!

Problem: It turns out that for file references, the .vcxproj file simply ignores files written with MsBuild variable references like my ($SolutionDir)..\folder\file.cpp -They show up when you view the .vcxproj file in a text editor, but not from within Solution Explorer. Update: Seems like the MsBuild variable actually sometimes works (see the strikeout above), but not in the combination with double dots for jumping one step up in the folder hierarchy. Needs verification what conditions are for this problem to occur.


Solution: Once I had replaced the ($SolutionDir)..\folder entries in the .vcxproj file with the more boring and less flexible ..\..\folder, everything was fine.

Saturday, May 25, 2013

Language neutral Pin shortcut to Start Menu using C#

Problem: I needed a program that would automatically pin an existing shortcut on the desktop to the start menu, regardless what localization the Windows user was using. I was using Windows Server 2008 R2 with a couple of alternate languages to English installed for testing. The program was written in C#. I hit the wall a copule of times while trying to make c# code from an earlier implementation written in VB.NET - this is a summary of what I got to work in the end:
Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
Object oShell = Activator.CreateInstance(shellAppType);
Shell32.Folder oFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, oShell, new object[] { 0 }); //25 = common desktop, 0 is local desktop
 


if (System.IO.File.Exists(ShortcutTarget) & (oFolder != null))
{
   Shell32.FolderItem oFolderItem = oFolder.ParseName("somefile.lnk");
   Shell32.ShellLinkObject oShellLink = (Shell32.ShellLinkObject)oFolderItem.GetLink;
   if (oShellLink != null)
   {
      // Find localized shell32 verb used to pin shortcut to the start menu (so that it works in any language)
      StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
      IntPtr hShell32 = LoadLibrary("SHELL32");
      LoadString(hShell32, 5381, szPinToStartLocalized, MAX_PATH); // 5381 is the DLL index for "Pin to start menu", ref. http://www.win7dll.info/shell32_dll.html
      string localizedVerb = szPinToStartLocalized.ToString();

      foreach (Shell32.FolderItemVerb verb in oFolderItem.Verbs())
      {
         if (verb.Name == localizedVerb)
         {
            verb.DoIt();
            break;
         }
      }
   }
}


You need to reference Shell32 - i.e. Microsoft Shell Controls and Automation on the COM tab of your "Add reference" dialog in VS2010. Also make sure you copy the shell32.interop.dll along with your application when you move the application out of your bin folder.

The following problems were encountered and solved on the way:

BadImageFormatException when entering the method containing this code. The code worked well on a Windows Vista computer, but crashed when running on Server 2008 R2. I assume this happened because of the fact that Server 2008 R2 is a 64 bit OS, and this did not work well with using the unmanaged Shell32.
Solution: Change the target CPU of your application to x86. If you use VS2010 Express, this tip on StackOverflow may be helpful to you - Make sure to read all the answers if you are stuck.

InvokeVerb did not work. Before ending up using the line verb.DoIt(), I tried using oFolderItem.InvokeVerb(verb.Name), which used to work in an earlier VB.NET implementation of the same code. I have no explanation to why this did not work, but it did not. A conspiracy theory is that Nike paid them off to just do it...

By the way, this earlier post mentions a problem I encountered trying to do the same in VB.NET some time ago. It probably applies here too, which is why the top three lines of the code looks like they do.

Monday, February 28, 2011

VS2010 crashes when editing

Problem: VS2010 crashes the instance you enter a character or paste text into a source file. The message displayed (sometimes - other times VS2010 simply dies and disappears without further notice) is:

Visual Studio has encountered an exception. This may be caused by an extension. You can get more information by running the application together with the /log parameter on the command line, and then examining the file 'C:\Users\USERNAME\AppData\Roaming\Microsoft\VisualStudio\10.0\ActivityLog.xml'

Solution: The solution was found in this forum, which states:
It appears to be due to missing registry information. Adding the default value to the below registry key solved the problem.
On 32-Bit Windows: [HKEY_CLASSES_ROOT\CLSID\{73B7DC00-F498-4ABD-AB79-D07AFD52F395}\InProcServer32]
On 64-Bit Windows: [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{73B7DC00-F498-4ABD-AB79-D07AFD52F395}\InProcServer32]
The "(Default)" value should be one of the following:On 32-Bit Windows: "C:\Program Files\Common Files\Microsoft Shared\MSEnv\TextMgrP.dll"
On 64-Bit Windows: "C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\TextMgrP.dll"