问题
I am trying to programmatically find the exe file that is run for a given MSI lnk file (advertised shortcut). I have used an approach similar to that shown in the answer to Is there a way to resolve a .lnk target that works for links that end up in c:\windows\installer?. This approach works fine for the majority of MSI lnk files. Unfortunately there are a minority of lnk files that run fine, but MsiGetShortcutTarget returns no component id. So the subsequent call to MsiGetComponentPath returns InvalidArg.
Here's the code I'm using (taken from here):
public const int MaxFeatureLength = 38;
public const int MaxGuidLength = 38;
public const int MaxPathLength = 1024;
public static string ParseShortcut(string shortcutFilename)
{
StringBuilder product = new StringBuilder(MaxGuidLength + 1);
StringBuilder feature = new StringBuilder(MaxFeatureLength + 1);
StringBuilder component = new StringBuilder(MaxGuidLength + 1);
var returnValue = MsiGetShortcutTarget(shortcutFilename, product, feature, component);
if (returnValue != 0)
{
return null;
}
int pathLength = MaxPathLength;
StringBuilder path = new StringBuilder(pathLength);
InstallState installState = MsiGetComponentPath(product.ToString(), component.ToString(), path, ref pathLength);
if (installState == InstallState.Local)
{
return path.ToString();
}
else
{
return null;
}
}
An example on my machine is C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\Office 2013 Tools\Office 2013 Language Preferences.lnk
Product id: {91150000-0011-0000-0000-0000000FF1CE} Feature id: SetLanguageFiles
I believe the IShellLink interface cannot be used to return the runnable exe for MSI Advertised Shortcuts and my attempts to do so have returned the path to an exe containing icon resources.
Clearly it is possible for the operating system to locate the appropriate exe (in this case it is C:\Program Files (x86)\Microsoft Office\Office15\SETLANG.EXE).
How do I get which exe file is associated with this lnk file using code?
回答1:
When no component id is returned from MsiGetShortcutTarget, it is possible to get the component id from the MSI database. One way of doing this is to use WiX DTF as shown here: https://stackoverflow.com/a/34680682/3051702.
The returned component id can then be used in a call to MsiGetComponentPath. Alternatively, the native methods could be used directly.
来源:https://stackoverflow.com/questions/34638433/msigetshortcuttarget-msi-lnk-files-return-no-component-id