Determining Installed Visual Studio Path for 2017 - powershell

I have a powershell script that looks at a list of VS installations, and determines the highest version installed. It then uses the InstallDir for that version, and uses it to access various commands.
It still uses the lower versions, however.
As of VS2017, it appears that the Registry keys are no longer saved in the same way. I need to update the script to be able to figure out the 2017 settings.
#Add New Versions to this list when new versions of VS are released
$VsVersionsToDisable = "10.0", "11.0", "12.0", "14.0"
[System.Collections.ArrayList]$VsVersions = $VsVersionsToDisable
#Find the Highest installed VS Version, and use it for the TFS.exe Command.
foreach ($version in $VsVersions | Sort-Object -Descending)
{
$keyPath = "HKCU:\Software\Microsoft\VisualStudio\$version`_Config"
If (Test-Path $keyPath)
{
$aliasPath = Get-ItemProperty -Path $keyPath | Select-Object `
-ExpandProperty InstallDir
$proxyPath = Join-Path $aliasPath "tf.exe"
set-alias proxyTF $proxyPath
}
}
To avoid an XY question: We use this script to configure the TFS Proxy settings for a user. It determines the highest installed version, uses it to find the proxy, then iterates through the lower versions configuring their proxy settings with the same value.
What is the best way to determine the installation directory (and also the tf.exe location) for VS2017?

From what I can see, use the SxS\VS7 option:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7
It should give you the root paths to Visual Studio:
That should get you going.
The tf.exe location is then stored using a symlink under:
.\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\tf.exe

Since you're using PowerShell, check out https://github.com/microsoft/vssetup.powershell, which is a PS module for detecting installations of VS2017+.
Otherwise, you could need to rely on the Nuget package which is the supported means of detecting VS.
See also this answer on a related question, which predates the PS module I listed above but contains some unsupported methods for finding VS.

I did use this as a reference and came to a solution in another way.
I'm not sure how resilient it is with regards to other versions, but it did the trick for me. It get's the directory of devenv and then I add the extra on the end for TFS. Obviously if the structure is different, then we are screwed.
Hope it helps.
$regKey = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\devenv.exe"
$visualStudioDir = Get-ItemPropertyValue -Path $regKey -Name "(Default)"
$visualStudioDir = ($visualStudioDir.Replace("devenv.exe","")).replace("`"","")
$tfsPath = 'CommonExtensions\Microsoft\TeamFoundation\Team Explorer\tf.exe'
Set-Alias tf $visualStudioDir$tfsPath
tf workspaces

Related

How to change extended windows file attributes via Powershell without using attrib.exe?

This seems to be a quite simple question, yet googling gave me nothing.
Here is the error (PS 5.1, win 10.0.14393 x64):
Set-ItemProperty $myFileInfo -Name Attributes -Value ([System.IO.FileAttributes]::Temporary)
The attribute cannot be set because attributes are not supported. Only the following attributes can be set: Archive, Hidden, Normal, ReadOnly, or System.
attrib.exe seems to support most of System.IO.FileAttributes. Unfortunately is does not seem to work with files referenced using FileSystem PSDrives. That is what I am using extensively.
Making wrapper for SetFileAttributes kernel API call would be the last resort.
Am I missing any other [more simple] ways setting these extended file attributes?
PS. Apart from [System.IO.FileAttributes]::Temporary I am interested in setting [System.IO.FileAttributes]::NotContentIndexed.
You can edit the Attributes property of a [FileInfo] object directly. For example, if you wanted to exclude all files in the C:\Temp folder from being content indexed, you could do this:
Get-ChildItem C:\Temp | ForEach{
$_.Attributes = $_.Attributes + [System.IO.FileAttributes]::NotContentIndexed
}
That would get each file, and then add the [System.IO.FileAttributes]::NotContentIndexed attribute to the existing attributes. You could probably filter the files to make sure that the attribute doesn't already exist before trying to add it, since that may throw errors (I don't know, I didn't try).
Edit: As noted by #grunge this does not work in Windows Server 2012 R2. Instead what you have to do is reference the value__ property, which is the bitwise flag value, and add the bitwise flag for NotContentIndexed. This should work for you on any Windows OS:
Get-ChildItem C:\Temp | ForEach{
$_.Attributes = [System.IO.FileAttributes]($_.Attributes.value__ + 8192)
}

Use Powershell to delete file from a folder set by windows registry value

Sorry if this has been answered before, I have tirelessly searched and cannot find the exact answer I am a Mac user and have not ventured into Windows registry before.
I am creating an installer for audio plugins and have a separate demo version of the titles. In the registry for the demo version, I have the entry
Demo=1
and also have paths set for various components of the plugins, which are optionally installed, these are stored in the registry as the user may install these into different directories depending on their host software
VST3=C:\Somepath\VST3
VST32=C\AnotherPath\VSTPlugins
VST64=C\AnotherPathAgain\VSTPlugins
I have found how to search the registry to check if Demo=1
$val = Get-ItemProperty -Path hklm:software\Audio Vitamins\Structure -Name “Demo”
if($val.Demo -eq 1)
{
**** This is where I need help *****
}
How do I set Powershell to remove a particular file 'structure.vst3' from the path set in VST3 or or 'structure.dll' from the paths set in VST32 and VST64. Note these can all be present or only 1 of them depending on the original install.
You have a couple of different paths (pun intended) you can take here.
You can organize your "demo = 1" files into one folder and the others in another and reference the demo folder location in the registry. Then you get the file location and use del to remove them. Much easier and doesn't require you to track which ones are there with unnecessary registry entries.
$demofolder = gp -path HKLM:\path\to\registry\key -Name "demofolder"
dir $demofolder -file|%{del $_ -force}

How can I find the Microsoft Edge version on Windows 10 in powershell?

I've searched through the SOFTWARE\Classes and SOFTWARE\Microsoft subkeys, but couldn't find anything related to "spartan" or "edge". Given that Edge is still very new, there really isn't much information about this yet.
As an example, this is how I gather the information about the Internet Explorer Version via the registry on a remote machine:
$ieVersion=[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $args[0]).OpenSubKey('SOFTWARE\Microsoft\Internet Explorer').GetValue('SvcVersion')
Use the Get-AppxPackage command:
Get-AppxPackage -Name Microsoft.MicrosoftEdge | Foreach Version
The package name is valid on build 10240 but if you are on an earlier build, it might be different. If the above doesn't find the package try -Name *Edge* or -Name *Spartan*.
$productPath = $Env:WinDir + "\SystemApps\Microsoft.MicrosoftEdge_*\MicrosoftEdge.exe"
If(Test-Path $productPath) {
$productProperty = Get-ItemProperty -Path $productPath
Write-Host $productProperty.VersionInfo.ProductVersion
}
Else {
Write-Host "Not find Microsoft Edge."
}
Source How to determine the version of Microsoft Edge browser by PowerShell
For Edge on Chromium above 44 version
powershell:
Get-AppxPackage -Name *MicrosoftEdge.* | Foreach Version
cmd:
powershell "Get-AppxPackage -Name *MicrosoftEdge.* | Foreach Version"
I tested using two commands back to back. I ran from an elevated PowerShell session New-PSSession -ComputerName "The remote PC I was testing this on." and then once the connection was made I ran the Get-AppxPackage -Name Microsoft.MicsrosoftEdge and it pulled down the information, but I think it was more build information. You can also filter it down to version using the Pipe character. The full command looked like this.
Get-AppxPackage -Name Microsoft.MicrosoftEdge | select-object Version
I found this forum and others that lead me to some of the other switches and parameters I did not know about.
How can I find the Microsoft Edge version on Windows 10 in powershell?
I was trying to find an alternate way of remotely finding out what browser version it was. Trying to verify if it is updating regularly. I am still learning. I hope this helps. I found another article that shows me exactly what I am looking for differently without powershell.
https://www.tenforums.com/tutorials/161325-how-find-version-microsoft-edge-chromium-installed.html#option2
You may see multiple versions of Edge installed via Appx-Packages. I would recommend this approach:
$EdgeExe = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\msedge.exe' "(default)"
$version = (Get-Item $EdgeExe).VersionInfo.ProductVersion

Powershell get latest on a working folder?

I am trying to get latest on a specific folder and was wondering how I would do this. I have been reading the MSDN documentation about the Workspace class but unfortunately it doesn't seem to provide any information about how I would go about getting latest of a specific folder.
For example, I have a single workspace but with multiple working folders. My PowerShell script can get latest but only at workspace level. Is it possible to get it from a working directory level or at a particular folder level?
Thanks in advance, DS.
EDIT
I believe this is possible as power tools is able to do it via right clicking a folder and getting latest. Ideally, want to replicate this.
http://msdn.microsoft.com/en-us/library/Microsoft.TeamFoundation.VersionControl.Client.Workspace.aspx
The below shows my script in practice..
$tfs = .\tfs-get-instance.ps1 -uri $uri
$vcs = $tfs.TfsTeamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
[psobject]$workspace = $vcs.GetWorkspace([System.Environment]::MachineName, [System.Environment]::UserName)
$workspace.Map($sourceFolder, $localFolder)
$result = $workspace.GetLocalItemForServerItem($sourceFolder);
if ($result -ne "")
{
echo $result
}
You should be able to use the Workspace.Get Method (String[], VersionSpec, RecursionType, GetOptions) to get what you want.
On the other hand, if you don't necessarily want to do it using the .NET objects, you could let tf.exe do the actual work, like the following:
& $TfExePath workfold /map "$codePath" "$LocalFolderPath" /collection:"$tfCollection" /workspace:$workspaceName
& $TfExePath get "$codePath" /version:$ChangeSet /force /overwrite /all /recursive $workspaceName
On the other hand, if you have the TF PowerTools installed you should also have PowerShell cmdlets for working with TFS. I have never used them, but I'm guessing you should be able to use them instead of using tf.exe if you want to. I would probably go for the PowerShell cmdlets in the power tools if they fill your need.

Get Latest Version of Folder from TFS, using Powershell

I am trying to "Get Latest Version" of a particular folder from TFS, using Powershell.
I have installed the TFS Snappin, and have been using TFS Power Tools cmdlets in PowerShell (such as Get-TfsChildItem and Select-TfsItem etc) [How do I set up TFS PowerShell Snapin ], and have gone through their documentation (which I didn't find explanatory enough!).
Confused, on the exact cmdlet to use, when I am trying to get the latest version of an entire Folder structure from TFS, that is mapped to my local drive (and not just a changeset or ChildItem).
Example :
Tfs Path - $/APD-RepairSolutions/Main/Database
Mapped path - D:\TFS\APD-RepairSolutions/Main/Database.
I want a code, that would iteratively get the latest version of the entire folder Database,( that has number of tables,stored procedures etc.)
I am using ..
PS D:\Tfs\APD-RepairSolutions\Main\Database> $server=Get-TfsServer -Name http://tfs:8080/tfs
PS D:\Tfs\APD-RepairSolutions\Main\Database> Get-TfsChangeset -Recurse -Server $Server
Not helping my case - as it is only returning the latest changeset in the current directory.
To get latest (tf get) use Update-TfsWorkspace.
Get-TfsChangeset is the equivalent of tf changeset.
Gotcha! with Update-TFSWorskpace. Has some helpful parameters as well. -Items is used to specify the exact items you want to update.
PS D:\Tfs\APD-RepairSolutions\Main>Update-TFSWorkspace -All -Overwrite -Force -Recurse -Items .\Database
The Workspace is replaced with updated versions of items. Thanks #Kmoraz!
If you would like to use the TFS API instead, you can use the Workspace.Get Method:
# Load the TFS assemblies
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")
$ws = $vcServer.QueryWorkspaces("<WORKSPACENAME>", $null, $null);
# Specify properties of intended workspace get
$recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full
$latestVersion = [Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest
$getOptions = [Microsoft.TeamFoundation.VersionControl.Client.GetOptions]::GetAll
# Get what I want!
$ws.Get("$/Remote/Folder", $latestVersion, $recursionType, $getOptions)
Would be a good idea to replace the nulls with your domain login and computer name when Querying Workspaces.