How to get installed VisualStudio extensions programmatically? - visual-studio

How can I get a list of installed VisualStudio extensions? Somehow through DTE? Just the names would be fair enough.

Does this help:
System.IServiceProvider serviceProvider = package as System.IServiceProvider;
Microsoft.VisualStudio.ExtensionManager.IVsExtensionManager em =
(Microsoft.VisualStudio.ExtensionManager.IVsExtensionManager)serviceProvider.GetService(
typeof(Microsoft.VisualStudio.ExtensionManager.SVsExtensionManager));
string result = "";
foreach(Microsoft.VisualStudio.ExtensionManager.IInstalledExtension i in em.GetInstalledExtensions())
{
Microsoft.VisualStudio.ExtensionManager.IExtensionHeader h = i.Header;
if (!h.SystemComponent)
result += h.Name + " (by " + h.Author + ") v" + h.Version + " " + h.MoreInfoUrl + System.Environment.NewLine;
}
Copied from https://vlasovstudio.com/visual-commander/commands.html #20.

Another possibility, if you don't want DTE, because you are not running from within Visual Studio or are concerned about performance you can query the extensions from the file system / registry:
For User Extensions
%LocalAppData%\Microsoft\VisualStudio*.vsix
For General Extensions
\Common7\IDE\Extensions*.vsix
IF you want to be 100% correct you can look up the paths in
\Common7\IDE\devenv.pkgdef
NOTE: There can be additional paths in the PkgDefSearchPath.
To check wether a User Extensions is enabled or not you have to query the registry:
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\ExtensionManager\EnabledExtensions
There are some other rules that apply, which you can find in this blog from Microsoft:
http://blogs.msdn.com/b/visualstudio/archive/2010/02/19/how-vsix-extensions-are-discovered-and-loaded-in-vs-2010.aspx

Related

Set mitmdump proving multi domain

You need to set up map-remote on multiple phone URLs in autotest, but how do you do it via the command line?
launch example:
case ANDROID -> {
String[] command = {"mitmdump",
"--listen-port", String.valueOf(port),
"--set", "confdir=" + Objects.requireNonNull(Proxy.class.getClassLoader().getResource("mitmproxy")).toURI().getPath() + "/mitmproxy-certs",
"--map-remote", "|" + mapRemotePattern + "|http://localhost:" + String.valueOf(mockPort),
"--modify-headers", "/~hq localhost/Host/" + hostHeader,
"--save-stream-file", fileNameNetworkLog};
startMitmdump(command);
}
I can't find the answer in the documentation
when trying to add 1 more map-remote field with different url, then it doesn't work
If you try to write mapRemote by regular expression OR, to 2 url , then it doesn't work either.

How to detect if /norestart is provided running msi

I'm building MSi using visual studio setup project. I want to have different custom action run depending on /norstart option. What condition should I use to detect if /norestart is provided or not?
If this is impossible, I'm thinking about setting a property. Here is my theory. Use Orca to set REBOOT=Force. If I want to suppress reboot, run msi as
foo.msi /quiet REBOOT=ReallySuppress
And read the property from code, like
String inputFile = #"C:\Users\Administrator\Desktop\foo.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer) Activator.CreateInstance(installerType);
// Open the MSI database in the input file
var database = installer.OpenDatabase(inputFile, 0);
// Open a view on the Property table for the version property
var view = database.OpenView("SELECT * FROM `Property`");
//View view = database.OpenView("SELECT * FROM Property");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
// Get the version from the data
//string version = record.get_StringData(2);
while (record != null)
{
logger.LogMessage(record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
}
This doesn't work, because it always read REBOOT=Force.
I have figured this out by myself.
Set CustomActionData to be /reboot=[REBOOT].
Then read the value:
Context.Parameters["reboot"]
If /norestart option is provided, value of reboot will be ReallySuppress

SCons support for visual studio 2013

Does anyone know when scons will support Visual Studio 2013?
The latest release, 2.3.1, is hard coded to look for 6.0 up to 11.0. But no entries for 12.0.
VS 2013 has been released for a few months. I'm surprised this is lacking.
Thanks
Shane
I too was looking for VS 2013 (vs12) support (for scone 2.3.0) and I found this link:
D146 SCons visual studio 2013 support
I made the same simple changes to the 3 files as described there, and, voila, vs12 now works...
Unmarking as an answer. Turns out there was an issue on a machine with just VS2013.
I managed to work around it by calling
SCons.Tool.MSCommon.vc.​__INSTALLED_VCS_RUN=['12.0']
It works. But such a bad practice that I can't encourage it in good faith.
It turns out official support is still pending. I've talked to the developers and they believe it should be part of the next release.
Like hplate I came across a patch for scons.
https://bitbucket.org/scons/scons/pull-request/104/support-visual-studio-2013/diff
The code here only supports VS2013 Express. But it was simple to modify it for VS2013.
That worked well enough. But I did not want to force ~300 other developers to use a patched version of scons.
Luckily our build system creates one Environment & clones it as needed. My solution
def RegGetValue(root, key, _32bit = True):
"""This utility function returns a value in the registry
without having to open the key first. Only available on
Windows platforms with a version of Python that can read the
registry.
"""
if not SCons.Util.can_read_reg:
print "ERROR: Python cannot read the Windows registry! - Crashing out..."
sys.exit(-1)
p = key.rfind('\\') + 1
keyp = key[:p-1] # -1 to omit trailing slash
val = key[p:]
if _32bit:
flags = 0x20219 # KEY_READ (0x20019), KEY_WOW64_32KEY (0x0200)
else:
flags = 0x20119 # KEY_READ (0x20019), KEY_WOW64_64KEY (0x0100)
try:
k = SCons.Util.RegOpenKeyEx(root, keyp, 0, flags)
except Exception as e:
import traceback
traceback.print_stack()
print "ERROR: Python cannot read the Windows registry (" + key + ")"
print "Please ensure you have the correct Visual Studio, Micrsoft SDK, and ​.NET installed"
print "Crashing out....."
sys.exit(-1)
return str(SCons.Util.RegQueryValueEx(k,val)[​0])
# As of version 2.3.1 scon's does not have built in support for Visual Studio 2013.
# Manually setting the appropriate environmental settings after the env has been created.
# Once scons officially supports 2013 consider removing these.
# HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client\InstallPath
# C:\Windows\Microsoft.NET\Framework64\v4.0.30319\
dot_net4_directory = RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client\\InstallPath", _32bit=False)
# HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\Setup\VS
# C:\Program Files (x86)\Microsoft Visual Studio 12.0\
vs_2013_directory = RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Microsoft\\VisualStudio\\12.0\\Setup\\VS\\ProductDir")
# HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots\KitsRoot81
# C:\Program Files (x86)\Windows Kits\8.1\
kit8_1_directory = RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots\\KitsRoot81")
# HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1A\InstallationFolder
# C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\
# Need to investigate if this should be 8.1A
sdk_8_1_directory = RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.1\\InstallationFolder")
LIBPATH = (
dot_net4_directory + ';'
+ vs_2013_directory + 'VC\\LIB\\amd64;'
+ vs_2013_directory + 'VC\\ATLMFC\\LIB\\amd64;'
+ kit8_1_directory + 'References\\CommonConfiguration\\Neutral;'
+ '\\Microsoft.VCLibs\\12.0\\References\\CommonConfiguration\\neutral'
)
LIB = (
vs_2013_directory + 'VC\\LIB\\amd64;'
+ vs_2013_directory + 'VC\\ATLMFC\\LIB\\amd64;'
+ kit8_1_directory + 'lib\\winv6.3\\um\\x64'
)
PATH = (
vs_2013_directory + 'Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow;'
+ vs_2013_directory + 'VC\\BIN\\amd64;'
+ dot_net4_directory + ';'
+ vs_2013_directory + 'VC\\VCPackages;'
+ vs_2013_directory + 'Common7\\IDE;'
+ vs_2013_directory + 'Common7\\Tools;'
+ vs_2013_directory + 'Team Tools\\Performance Tools\\x64;'
+ vs_2013_directory + 'Team Tools\\Performance Tools;'
+ kit8_1_directory + 'bin\\x64;'
+ kit8_1_directory + 'bin\\x86;'
+ sdk_8_1_directory + 'bin\\NETFX 4.5.1 Tools\\x64\\;'
+ 'C:\\Windows\\System32'
)
INCLUDE = (
vs_2013_directory + 'VC\\INCLUDE;'
+ vs_2013_directory + 'VC\\ATLMFC\\INCLUDE;'
+ kit8_1_directory + 'include\\shared;'
+ kit8_1_directory + 'include\\um;'
+ kit8_1_directory + 'include\\winrt'
)
# Setup the Visual Studio 2013 variables
# Note: The default 'ENV' values are fine
# on a machine with VS2008 & VS2010 installed
# Unclear about machines with just VS2013.
# Needs investigation.
# env['ENV']['TMP'] = default
# env['ENV']['COMSPEC'] = default
# env['ENV']['TEMP'] = default
# env['ENV']['SystemDrive'] = default
# env['ENV']['PATHEXT'] = default
env['ENV']['LIBPATH'] = LIBPATH
env['ENV']['LIB'] = LIB
env['ENV']['PATH'] = PATH
# env['ENV']['SystemRoot'] = default
env['ENV']['INCLUDE'] = INCLUDE
env['MSVC_VERSION'] = '12.0'
env['GET_MSVSPROJECTSUFFIX'] = '.vcxproj'
env['MSVSPROJECTSUFFIX'] = '.vcxproj'
env['MSVS'] = {'SOLUTIONSUFFIX': '.sln', 'PROJECTSUFFIX': '.vcxproj'}
env['MSVSENCODING'] = 'utf-8'
env['MSVS_VERSION'] = '12.0'
Caveat: So far I've only tested this on a machine with VS2008, VS2010, & 2013 installed. I'm going to test it on VS2013 only machine and will update this post if there are any issues.
FYI. VS2013 support should be available in the next release of SCons (aka 2.3.2). The pull requests have been merged.
https://bitbucket.org/scons/scons/pull-request/104/support-visual-studio-2013/diff
https://bitbucket.org/scons/scons/pull-request/120/adding-support-for-visual-studio-2013/diff
Visual Studio is now part of the latest scons releases. If this will not work for you I suggest look at hplate's answer.

Exporting a CSV file from MVC3 - Internet Explorer Issue

I'm trying to create a CSV export for some data I have. Seems simple enough, and works beautifully in Firefox and Chrome, but in Internet Explorer I just get a message saying the file could not be downloaded. No other error messages, no break in Visual Studio, no debugging information that I can find.
Here's my code. Perhaps I'm doing something wrong?
public ActionResult ExportStudentsCSV(IEnumerable<Student> students) {
MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, System.Text.Encoding.UTF8);
writer.WriteLine("Username,Year Level,School Name,State,Date Joined");
foreach (Student student in students) {
writer.WriteLine(
"\"" + student.username
+ "\",\"" + student.year_level
+ "\",\"" + student.SchoolName
+ "\",\"" + student.state
+ "\",\"" + student.join_date
+ "\""
);
}
writer.Flush();
output.Seek(0, SeekOrigin.Begin);
return File(output, "text/csv", "Students_" + DateTime.Now.ToShortDateString().Replace('/', '-') + ".csv");
}
And I'm calling this function in my controller with:
return ExportStudentsCSV(model.StudentReport.StudentList);
You may need to add a Content-Disposition header.
In your ExportStudentsCSV function, before returning:
var cd = new System.Net.Mime.ContentDisposition();
cd.FileName = "filename.csv";
Response.AddHeader("Content-Disposition", cd.ToString());
Or if you'd rather be brief about it (equivalent to above):
Response.AddHeader("Content-Disposition", "attachment;filename=filename.csv");
It may seem dodgy to be answering my own question, but I thought my experience may help someone. I did some more digging and found a completely alternate way of doing this using DataTables and a specific CsvActionResult which inherits from FileResult.
See this gist: https://gist.github.com/777376
Probably has something to do with the Content-Type/Content-Dispositon because IE follows standards when it wants to.
Check out ASP MVC3 FileResult with accents + IE8 - bugged?

How to get the installation directory?

The MSI stores the installation directory for the future uninstall tasks.
Using the INSTALLPROPERTY_INSTALLLOCATION property (that is "InstallLocation") works only the installer has set the ARPINSTALLLOCATION property during the installation. But this property is optional and almost nobody uses it.
How could I retrieve the installation directory?
Use a registry key to keep track of your install directory, that way you can reference it when upgrading and removing the product.
Using WIX I would create a Component that creates the key, right after the Directy tag of the install directory, declaration
I'd use MsiGetComponentPath() - you need the ProductId and a ComponentId, but you get the full path to the installed file - just pick one that goes to the location of your installation directory. If you want to get the value of a directory for any random MSI, I do not believe there is an API that lets you do that.
I would try to use Installer.OpenProduct(productcode). This opens a session, on which you can then ask for Property("TARGETDIR").
Try this:
var sPath = this.Context.Parameters["assemblypath"].ToString();
As stated elsewhere in the thread, I normally write a registry key in HKLM to be able to easily retrieve the installation directory for subsequent installs.
In cases when I am dealing with a setup that hasn't done this, I use the built-in Windows Installer feature AppSearch: http://msdn.microsoft.com/en-us/library/aa367578(v=vs.85).aspx to locate the directory of the previous install by specifying a file signature to look for.
A file signature can consist of the file name, file size and file version and other file properties. Each signature can be specified with a certain degree of flexibility so you can find different versions of the the same file for instance by specifying a version range to look for. Please check the SDK documentation: http://msdn.microsoft.com/en-us/library/aa371853(v=vs.85).aspx
In most cases I use the main application EXE and set a tight signature by looking for a narrow version range of the file with the correct version and date.
Recently I needed to automate Natural Docs install through Ketarin. I could assume it was installed into default path (%ProgramFiles(x86)%\Natural Docs), but I decided to take a safe approach. Sadly, even if the installer created a key on HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall, none of it's value lead me to find the install dir.
The Stein answer suggests AppSearch MSI function, and it looks interesting, but sadly Natural Docs MSI installer doesn't provide a Signature table to his approach works.
So I decided to search through registry to find any reference to Natural Docs install dir, and I find one into HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components key.
I developed a Reg Class in C# for Ketarin that allows recursion. So I look all values through HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components and if the Main application executable (NaturalDocs.exe) is found into one of subkeys values, it's extracted (C:\Program Files (x86)\Natural Docs\NaturalDocs.exe becomes C:\Program Files (x86)\Natural Docs) and it's added to the system environment variable %PATH% (So I can call "NaturalDocs.exe" directly instead of using full path).
The Registry "class" (functions, actually) can be found on GitHub (RegClassCS).
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("NaturalDocs.exe", "-h");
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
var process = System.Diagnostics.Process.Start (startInfo);
process.WaitForExit();
if (process.ExitCode != 0)
{
string Components = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components";
bool breakFlag = false;
string hKeyName = "HKEY_LOCAL_MACHINE";
if (Environment.Is64BitOperatingSystem)
{
hKeyName = "HKEY_LOCAL_MACHINE64";
}
string[] subKeyNames = RegGetSubKeyNames(hKeyName, Components);
// Array.Reverse(subKeyNames);
for(int i = 0; i <= subKeyNames.Length - 1; i++)
{
string[] valueNames = RegGetValueNames(hKeyName, subKeyNames[i]);
foreach(string valueName in valueNames)
{
string valueKind = RegGetValueKind(hKeyName, subKeyNames[i], valueName);
switch(valueKind)
{
case "REG_SZ":
// case "REG_EXPAND_SZ":
// case "REG_BINARY":
string valueSZ = (RegGetValue(hKeyName, subKeyNames[i], valueName) as String);
if (valueSZ.IndexOf("NaturalDocs.exe") != -1)
{
startInfo = new System.Diagnostics.ProcessStartInfo("setx", "path \"%path%;" + System.IO.Path.GetDirectoryName(valueSZ) + "\" /M");
startInfo.Verb = "runas";
process = System.Diagnostics.Process.Start (startInfo);
process.WaitForExit();
if (process.ExitCode != 0)
{
Abort("SETX failed.");
}
breakFlag = true;
}
break;
/*
case "REG_MULTI_SZ":
string[] valueMultiSZ = (string[])RegGetValue("HKEY_CURRENT_USER", subKeyNames[i], valueKind);
for(int k = 0; k <= valueMultiSZ.Length - 1; k++)
{
Ketarin.Forms.LogDialog.Log("valueMultiSZ[" + k + "] = " + valueMultiSZ[k]);
}
break;
*/
default:
break;
}
if (breakFlag)
{
break;
}
}
if (breakFlag)
{
break;
}
}
}
Even if you don't use Ketarin, you can easily paste the function and build it through Visual Studio or CSC.
A more general approach can be taken using RegClassVBS that allow registry key recursion and doesn't depend on .NET Framework platform or build processes.
Please note that the process of enumerating the Components Key can be CPU intense. The example above has a Length parameter, that you can use to show some progress to the user (maybe something like "i from (subKeysName.Length - 1) keys remaining" - be creative). A similar approach can be taken in RegClassVBS.
Both classes (RegClassCS and RegClassVBS) have documentation and examples that can guide you, and you can use it in any software and contribute to the development of them making a commit on the git repo, and (of course) opening a issue on it's github pages if you find any problem that you couldn't resolve yourself so we can try to reproduce the issue to figure out what we can do about it. =)

Resources