Identify 'Current' open workspace through TFS API? - api

Is there a way to programatically determine the current workspace of the open sln/proj in visual studio using the TFS API? I've seen how the VersionControlServer can retreive all of the known workspaces, but is there anything I can use to tie that to what the user currently has (or doesn't have) open?

There is another override to the GetWorkspace method of an instantiated VersionControlServer object. You can call GetWorkspace with the local path like Bernhard states, but you can also call it with the workspace name and workspace owner. Since the workspace name defaults to the local computer name, you can usually get away with using Environment.MachineName, but there is always going to be that developer who changes the workspace name.
Example:
TeamFoundationServerFactory _tfs = TeamFoundationServerFactory.GetServer(server);
_tfs.EnsureAuthenticated();
VersionControlServer _vcs = (VersionControlServer)_tfs.GetService(typeof(VersionControlServer));
Workspace _ws = _vcs.GetWorkspace(Environment.MachineName, Environment.UserName);

If you can determine the physical path of the solution or project file, then you can query that file in TFS and you should see which workspace has been mapped to that local file location.

The problem with the approach from Dave Teply is that it assumes you already have an instance of a VersionControlServer or at least the TeamFoundationServerUri.
There is a more powerful way though, using the Workstation class. Ricci Gian Maria has written a quite extensive blog post about this topic. The below snippet is the essentials of that post:
Use the Workstation class to get the WorkspaceInfo for the path you're looking for, this will search the workpaces for all TFS servers registered on that workstation to see if there's a match:
Workstation workstation = Workstation.Current;
WorkspaceInfo info = workstation.GetLocalWorkspaceInfo(path);
Now that you have the WorkspaceInfo, you can sue it to connect to TFS, the workspace info contains the ProjectCollectionUri for that specific team project collection. And from that the Workspace instance:
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(info.ServerUri);
Workspace workspace = info.GetWorkspace(collection);
Use the collection or the workspace to then get access to the VersionControlServer:
VersionControlServer versionControlServer = collection.GetService<VersionControlServer>();

Related

How to configure cache folder for SourceDiskCache?

I understand from the documentation that the SourceDiskCache folder cannot be configured using the XML configuration file and is only available "through code installation". However I can't figure out how!
I need to configure a custom folder. I have tried a few different things, with different results (both in Application_Start):
This doesn't throw an error, but uses the default folder (/cache)
var sourceDiskCachePlugin = new SourceDiskCachePlugin {VirtualCacheDir = "~/App_Data/cache"};
Config.Current.Plugins.GetOrInstall(sourceDiskCachePlugin);
This (and most other variations I have tried) throws the error "SourceDiskCache settings may not be adjusted after it is started."
new SourceDiskCachePlugin().Install(Config.Current);
Config.Current.Plugins.Get<SourceDiskCachePlugin>().VirtualCacheDir = "~/App_Data/cache";
How can I configure this?
Also, the documentation states that SourceDiskCache is in beta - is this still the case, and will XML configuration ever be available?
This would be the normal way to configure and install it:
var plugin = new SourceDiskCachePlugin()
plugin.VirtualCacheDir = "~/App_Data/cache";
plugin.Install(Config.Current);
If your code is running more than once, use Config.Current.Plugins.GetOrInstall(plugin); It's best if you only install the plugin during Application_Start.
However, approach #1 from your question should work equally well, as long as you've set the right NTFS permissions on App_Data.

With scope based repository workpsace will all the members be able to check in the code.?

With scope based repository workpsace will all the members be able to check in the code.?
Or only deliver to the stream is possible like public repository work space.
With scope based repository workpsace will all the members be able to check in the code.?
No: only the owner of a repo workspace can check in code, or accept change set from other flow targets.
Or only deliver to the stream is possible like public repository work space.
No: only the owner of a repo workspace can initiate a deliver.
If you want to deliver change set from another repo workspace, you have to accept them in your own repo workspace first (by modifying its flow target in order to temporarily point to that other repo workspace), and then, once accepted, you can deliver them to the stream.

Replacing a .NET dll

I have a dll which is installed with the initial installation of my app (via an msi file). The dll contains a user key and this is 'demo' for the initial installation. When a user buys a licence he is provided with another dll which contains his name. The second dll is simply the first, rebuilt with a different name so it is the same GUID and file name.
This works fine on my win7 test machine, I can replace the dll in my apps dir and it runs correctly. I have recently provided a user dll to a new client but the replace method doesn't seem to work. He is quite IT literate so I think he is following the emailed instruction (replace the userdata.dll in your app directory with the attached) it does not seem to change the dll. He is using Win8(pro).
I had thought of sending him an Inno setup to copy the user dll into the app dir, Flags:ignorereversion regserver sharedfile
Can anyone suggest a solution or an explanation?
Later...
I have now sent him an Inno setup for the updated dll and this works. If I used the second dll method (a good idea) I would still need to have the user install it.
Rather than replacing the original .dll, why not provide a second .dll with the customer's specific info? The 2nd .dll will unlock features in the original .dll.
For instance, in your original .dll you might check for Customer.dll:
if(TryLoadAssembly("Customer.dll", out assembly)) {
if(Validate(assembly)){
IsUnlocked = true;
}
}
Further recommendations (and untested samples) - have Customer.dll contain a single object implementing an interface:
class Customer : IToken {
GUID Guid {get;}
// other fields
}
To validate:
bool Validate(Assembly assembly){
Type type = assembly.GetType("Customer");
IToken customerToken = (IToken)Activator.CreateInstance(type);
// check some properties
return customerToken.Guid == application.Guid;
}
You say it doesn't appear to be replacing the DLL. Is it UAC redirecting his filecopy into local storage?
If this is the case then the easiest way to deal with it would be to either
1) supply a batch file that can do the file copy, along with instructions to launch the batch file by right clicking on it anc choosing "run as administrator".
2) supply an executable that can do the file copy. You can either include instructions to run the exe as an administrator like the batch file, or you can include a manifest with the application to instruct windows that the file needs to execute as an administrator.
A last option, which might be worth while for troubleshooting would be to get the user to turn off UAC and try the file copy again. If that works then this user will be happy and you know what the problem is and can find an elegant solution for future customers.
I've just looked on my Win 8 laptop and the option for UAC is in Control Panel - User Accounts - User Accounts - Change user account control settings. This will give a slider which can be slid all the way to the bottom to turn off UAC.
(User Accounts really is listed twice.)

Where am I going wrong with the persistence of User scoped Settings?

I have a Boolean, user scoped setting. I access it through a referenced class library, called Settings. This class library has a Module with properties:
Module AppSettings
Public Property MyBooleanSetting() As Boolean
Get
Return My.Settings.MyBooleanSetting
End Get
Set(ByVal value As Boolean)
My.Settings.MyBooleanSetting = value
My.Settings.Save()
End Set
End Property
End Module
I defined the setting in the Property pages of the Settings class library.
When other code manipulates the setting it will use code like:
Settings.MyBooleanSetting=True
While the code is running this works. But after a restart of the application the new value is not persisted.
Where am I going wrong?
After looking at the Using My.Settings in Visual Basic 2005 MSDN article and these MSDN Forum Threads , I would say you need to verify which path is being used.
User-scope settings are specific for each user. They can be read and set safely by the application code at run time. These settings are stored in a user.config file. To be technically accurate, there are two user.configs per user per application—one for non-roaming and one for roaming. Although the Visual Basic 2005 documentation states that the user.config file will be named according to the user's name (joe.config), this is not the case. The user.config file is created in the \[Local Settings]Application Data\\\. Where:
• is the user data directory, either non-roaming (Local Settings above) or roaming.
• is the user name.
• is the CompanyNameAttribute value, if available. Otherwise, ignore this element.
• is the AppDomain.CurrentDomain.FriendlyName. This usually defaults to the .exe name.
• is the URL, StrongName, or Path, based on the evidence available to hash.
• is a SHA1 hash of evidence gathered from the CurrentDomain, in the following order of preference:
a.StrongName
b.URL
If neither of these is available, use the .exe path.
• is the AssemblyInfo's AssemblyVersionAttribute setting.
Save your breath guys. The code did work after all. I used an other Property in the Viewmodel of my application that cached the Setting.MyBooleanSetting, but I forgot to read it in at application startup...

My application fails to create MAPI/Messaging profile properly using MAPI subsystem

I have an application which creates a MAPI profile to send mails/messages. The profile is getting created properly on Outlook2007 environment, but it is not getting created properly on Outlook2007 SP2 environment. Both the source code and "exchange environment to which MAPI/outlook profile" are same. The profile is created using MAPI subsystem.
Description about the application: The application is a windows service-based application. The service executes a COM application. The COM application spawns a new thread to create a new profile and sends a sample message.
Actual problem: During the profile creation, the call to the ConfigureMsgService function (that belongs to IMsgServiceAdmin) is not working properly even though it returns S_OK. The value for the 5th parameter "lpProps" of ConfigureMsgService function is given below.
// First, the mailbox name.
ZeroMemory(&rgval[0], sizeof(SPropValue) );
rgval[0].ulPropTag = PR_PROFILE_UNRESOLVED_NAME;
rgval[0].Value.lpszA = szMailbox;
// Next, the server name.
ZeroMemory(&rgval[1], sizeof(SPropValue) );
rgval[1].ulPropTag = PR_PROFILE_UNRESOLVED_SERVER;
rgval[1].Value.lpszA = szServer;
// For NT Services, need to do this to keep MAPI from
// displaying dialog boxes.
ZeroMemory(&rgval[2], sizeof(SPropValue) );
rgval[2].ulPropTag = PR_CONVERSION_PROHIBITED; //As the com application is executed by the NT service, this parameter is specified.
rgval[2].Value.b = TRUE;
Also note, prior to ConfigureMsgService function call, all the other MAPI calls such as MAPIInitialize, MAPIAdminProfiles, CreateProfile, AdminServices, CreateMsgService, GetMsgServiceTable etc are succeeded.
My question, the same code was working properly with Outlook 2007 environment, but it failed in Outlook 2007 SP2 environment.
Please note,
1. when the same code is executed from a stand-alone application, it worked fine.
2. The code didn't work properly if the service is executed as a Local System account or as a network service account.
What could be the problem? Am I missing some thing.
Is there any work-around is available?
Thanks in advance
Saravanan
Your problem is in #2 of your note:
Please note, 1. when the same code is
executed from a stand-alone
application, it worked fine. 2. The
code didn't work properly if the
service is executed as a Local System
account or as a network service
account.
MAPI profiles are stored in the current user's hive* in the registry (HKEY_CURRENT_USER and HKEY_USERS{user SID}). The system accounts (LocalSystem and NetworkService) don't present a user hive which MAPI needs to write the profile information.
The easiest fix is to have your service run under a user account which has been granted the Log On As Service right. Depending on how your COM app is run as (in proc vs out of proc) you may be able to have it run as a specific user instead of a system account.
*Hive is the term used for the different sections of the registry. Here we're just dealing with the user's own section of the registry.
Thanks for your reply.
I tried your idea, but it doesn't worked. I spoke to Microsoft in this case, they have provided a fix for this issue(http://support.microsoft.com/kb/972363), it fixed it.
Saravanan