FileVersionInfo doesn't match Details tab in Explorer - c#

I'm attempting to use C# and System.Diagnostics.FileVersionInfo to extract the version information from a list of files. My purpose for doing this is to keep track of unique filepath and version combinations. When the files change I'd like various things to happen depending on what exactly changed.
I've used both the FileVersion and ProductVersion properties of FileVersionInfo to no avail. Both report a different version number than what is reported in explorer.
An example using explorer.exe
Explorer Details tab reports: "6.1.7601.17567" (for both File and Product)
FVI.ProductVersion reports: "6.1.7600.16385"
FVI.FileVersion reports: "6.1.7600.16385 (win7_rtm.090713-1255)"

For some reason the ProductVersion property doesn't match the ProductMajorPart/MinorPart/BuildPart/PrivatePart... To get the actual version you can do this:
var fvi = FileVersionInfo.GetVersionInfo(path);
var productVersion = new Version(
fvi.ProductMajorPart,
fvi.ProductMinorPart,
fvi.ProductBuildPart,
fvi.ProductPrivatePart);
var fileVersion = new Version(
fvi.FileMajorPart,
fvi.FileMinorPart,
fvi.FileBuildPart,
fvi.FilePrivatePart);

Related

C# Open Registry Key when only a prefix portion of the name is known

I am working with these two registry keys.
64 bit Firefox version:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Mozilla Firefox (????)
32 bit Firefox version:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Mozilla Firefox xx.xx.xx (x86 en-US)
What I want is to read the key called InstallLocation inside that path. The issue is in the path. The path has Firefox version which has version number in it.
I can hard code the path, but when Firefox is updated, the the path is also updated, so it won't work after the update.
Is there a way to dynamically just read the part of the path and parse out the version to reach to the key?
In other words, is there a way to read the path up to Mozilla Fireox and ignore the rest, because I just want see if it this path exist, if it does, go inside the path to get the key-value.
Update
Thanks to konkked
var has32bit =
Registry.LocalMachine
.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")
.GetSubKeyNames()
.Any(a=>a.StartsWith("Mozilla Firefox"));
var has64bit =
Registry.LocalMachine
.OpenSubKey("SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
.GetSubKeyNames()
.Any(a=>a.StartsWith("Mozilla FireFox"));
How can I get a key-value inside the Mozilla Firefox folder?? Because the above code only returning true of false.
Try using below and it will have the install path
var path = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe", "", null);
You could get all of the subkeys of an entry using RegistryKey.GetSubKeyNames Method () and then do a where to see if any are FireFox
var has32bit =
Registry.LocalMachine
.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")
.GetSubKeyNames()
.Any(a=>a.StartsWith("Mozilla Firefox"));
var has64bit =
Registry.LocalMachine
.OpenSubKey("SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
.GetSubKeyNames()
.Any(a=>a.StartsWith("Mozilla FireFox"));
Also notice in a comment you said
There should be a better way to do this rather than collecting alllll (sic)
of the keys inside uninstall, as it can grow pretty big. #MarcB thank
you tho.
I don't think there is a better way to partially match against a subkey
And to answer comment :
Thank you! it's working. Is there a away (sic) to get values inside that
full path afte (sic) like InstallLocation
You can get the actual subkey when you decide which version you want, but I am not sure how you are going to decide that, but here is an example of how to access the values:
var subkey32BitBase =
Registry.LocalMachine
.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
var fireFoxKeys = subkey32BitBase.GetSubKeyNames(subkey32base);
foreach(var fireFoxSubKey in fireFoxSubKeys)
{
Console.WriteLine(
subkey32BitBase
.GetSubKey(fireFoxSubKey)
.GetValue("InstallLocation")
);
}
If Firefox is installed it will register itself to the "Open With..." list of HTML files.
The application names to open html files with are stored under the file type's registry key, under the OpenWithList subkey. The path to applications themselves are stored under HKCR\Applications.

How to find in VSPackage which version control system a solution uses

I'm new to extending Visual Studio and I'm trying to find way to find which source control system is used by current solution.
I created VsPackage project and I am able to obtain reference to solution via IVsSolution and to hook up to solution events via IVsSolutionEvents.
Inside OnAfterSolutionOpen (or possibly some other if there's an alternative) I would like to act differently basing on whether the solution uses TFS or Git or something else. How can I obtain this information?
I plan to support as many Visual Studio versions as possible, but if it isn't possible I would like to support at least VS2012 and higher.
Ok, after several hours of digging I've found a solution to this. Thanks to the article of Mark Rendle and the source code for his NoGit extension I've found, that the list of registered source control plugins is located in registry: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\SourceControlProviders (in case of VS 2013).
So now, we can have both plugin guid, and the name of the provider. This sample code can fetch those values:
var key = #"Software\Microsoft\VisualStudio\" + "12.0" + #"_Config\SourceControlProviders";
var subkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(key);
var providerNames = subkey.GetSubKeyNames().Dump();
var dict = new Dictionary<Guid, String>();
foreach (var provGuidString in subkey.GetSubKeyNames())
{
var provName = (string)subkey.OpenSubKey(provGuidString).GetValue("");
dict.Add(Guid.Parse(provGuidString), provName);
}
Now, there are two ways I've found to obtain guid of currently active provider.
important update: Apparently the second way of obtaining currently active plugin does not work as expected. I strongly advise using first solution.
This is the way that bases on the extension mentioned earlier:
var getProvider = GetService(typeof(IVsRegisterScciProvider)) as IVsGetScciProviderInterface;
Guid pGuid;
getProvider.GetSourceControlProviderID(out pGuid);
Or we can just go to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\CurrentSourceControlProvider and get the default value of this key:
var key2 = #"Software\Microsoft\VisualStudio\12.0\CurrentSourceControlProvider";
var guidString = (string)Microsoft.Win32.Registry.CurrentUser.OpenSubKey(key2).GetValue("");
var currentGuid = Guid.Parse(guidString);
Now we just take var activeProviderName = dict[currentGuid]; and that's all.

How to delete team project folder from source control?

I created folder with VersionControlServer.CreateTeamProjectFolder:
var connection = new TfsTeamProjectCollection(new Uri("http://my-tfs-serv:8080/tfs/DefaultCollection"));
var vcs = connection.GetService<VersionControlServer>();
vcs.CreateTeamProjectFolder(new TeamProjectFolderOptions("TestFolder"));
That call has created folder $/TestFolder/, now I want to delete it.
I could not find API for that. I tried to remove it with
TFSDeleteProject.exe /force /collection:http://my-tfs-serv:8080/tfs/DefaultCollection TestFolder
But it returns:
TF200016: The following project does not exist: TestFolder. Verify that the name of the project is correct and that the project exists on the specified Team Foundation Server.
Looks like VersionControlServer.CreateTeamProjectFolder() does not create a team project, it just creates the folder only.
But how can i remove that folder now?
TFSDeleteProject cmd won't work on items created with the code you are using. You can use the following code to delete(destroy):
var itemSpec = new ItemSpec(FullRepositoryPath, RecursionType.Full);
Item[] removedItems = TFSImplementor.VersionControl.Destroy(
itemSpec,
VersionSpec.Latest,
null,
DestroyFlags.StartCleanup);
TFSDeleteProject cmd will only work on projects created from Wizard.

get latest specific project in C#

I have a project that should be get latest to specific date. I have this code:
var serverFolder = pathInTfs;
var localFolder = pathInLocalMachin;
var workingFolder = new WorkingFolder(serverFolder, localFolder);
// Create a workspace mapping
workspace.CreateMapping(workingFolder);
if (!workspace.HasReadPermission)
{
throw new SecurityException(
String.Format("{0} does not have read permission for {1}",
versionControl.AuthorizedUser, serverFolder));
}
// Get the files from the repository
workspace.Get(dateForLatest, GetOptions.Overwrite);
every thing is good but I want to be get latest only directory "pathInTfs" in "pathInLocalMachin" but when program run workspace.Get() every project be get latest.
How I can get latest one path in my project.
There are several overloads of Get which allow you to specify the set of objects you want to get. For what you're doing, I think you want Get(GetRequest, GetOptions).
The GetRequest includes an ItemSpec where you can specify a folder to get, and then indicate RecursionType.Full.

How to get a ClickOnce application path and version number using C#/.NET code?

I want to get the path and version number of a ClickOnce application, provided the name of the ClickOnce application.
When I manually searched for it, I found it at the path as follows:
'C:\Users\krishnaim\AppData\Local\Apps\2.0\1HCG3KL0.K41\VO5BM4JR.RPO\head..tion_7446cb71d1187222_0005.0037_37dfcf0728461a82\HeadCount.exe'
But this keeps on changing, and it will become a hard-coded path. Is there another way to get a ClickOnce application (for example, HeadCount.exe which is already installed) path and version number using C#/.NET code?
It seems a little bizarre, but getting the current directory of the executing assembly is a bit tricky so my code below may be doing more than you think it should, but I assure you it is mitigating some issues where others may attempt to use Assembly.GetExecutingAssembly.Location property.
static public string AssemblyDirectory
{
get
{
//Don't use Assembly.GetExecutingAssembly().Location, instead use the CodeBase property
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return System.IO.Path.GetDirectoryName(path);
}
}
static public string AssemblyVersion
{
get
{
var asm = Assembly.GetExecutingAssembly();
//If you want the full four-part version number:
return asm.GetName().Version.ToString(4);
//You can reference asm.GetName().Version to get Major, Minor, MajorRevision, MinorRevision
//components individually and do with them as you please.
}
}
In order to do a ClickOnce application update you do not have to do so manually as long as you are using the standard deployment manifests (which I don't know how to ClickOnce unless you do use them).
The MSDN article Choosing a ClickOnce Update Strategy describes the different options for application updates.

Categories

Resources