성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[tree soap] 아차! f는 기억이 나는데, m은 ㅜㅜ 감사합니다!!! ^...
[정성태] 'm'은 decimal 타입의 숫자에 붙는 접미사입니다. ...
[정성태] https://lxr.sourceforge.io/ http...
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>"Visual Studio Enterprise is required to execute the test." 메시지와 관련된 코드 기록</h1> <p> 지난 글에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > mstest.exe 실행 시 "Visual Studio Enterprise is required to execute the test." 오류 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11886'>http://www.sysnet.pe.kr/2/0/11886</a> </pre> <br /> "Visual Studio Enterprise"가 설치되어 있는데도 "Visual Studio Enterprise is required to execute the test." 오류 메시지가 발생하는 상황을 설명했는데요, 그때의 스택 트레이스를 보면 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > (mstest.exe, PID 24268, Thread 21) ControllerExecution: Received exception calling InitializePlugin for test e77946db-2d9f-4453-b207-e1e3f83f7784: Microsoft.VisualStudio.TestTools.WebStress.LoadTestLicenseViolationException: Visual Studio Enterprise is required to execute the test. at Microsoft.VisualStudio.TestTools.WebStress.LoadTestUserLicenseManager.CheckForLoadTestExecution() at Microsoft.VisualStudio.TestTools.WebStress.LoadTestResultsCollector.Initialize(TestRun testRun, String[] agentNames) at Microsoft.VisualStudio.TestTools.WebStress.LoadTestControllerPlugin.Initialize(IControllerContext testContext) at Microsoft.VisualStudio.TestTools.Controller.ControllerPluginManager.InitializePlugin(Guid executionId) at Microsoft.VisualStudio.TestTools.Controller.ControllerExecution.SignalSyncStart(Object state) </pre> <br /> 이와 관련된 소스 코드들의 추적을 기록 차원에서 남깁니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.QualityTools.ControllerObject.dll // Microsoft.VisualStudio.QualityTools.ControllerObject, Version=16.0.0.0 internal class ControllerPluginManager { // Fields private Dictionary<Guid, ControllerPlugin> m_plugins; // Methods public ControllerPluginManager(); public void CleanupPlugins(); public void CleanupTest(Guid execId); public static IControllerPlugin CreateControllerPlugin(ITestElement testElement); public static void DeleteTestRun(Guid guidTestRunId, IExecutionRunConfiguration runConfig, ControllerInformation controllerInformation); public IControllerPlugin FindPlugin(Guid executionId); public void InitializePlugin(Guid executionId) { ControllerPlugin plugin; if (this.m_plugins.TryGetValue(executionId, out plugin) && (plugin != null)) { ControllerPlugin plugin2 = plugin; lock (plugin2) { if (plugin.Initialized) { return; } plugin.Initialized = true; } EqtTrace.Info("ControllerPluginManager: Calling Initialize on ControllerPlugin for test " + executionId.ToString()); plugin.Plugin.Initialize(plugin.Context); EqtTrace.Info("ControllerPluginManager: Calling TestAgentsReady on ControllerPlugin for test " + executionId.ToString()); plugin.Plugin.TestAgentsReady(plugin.Context.AgentNames); } } public IControllerPlugin LoadPlugin(ControllerExecution execution, ITestElement testElement); public void SetMessageSinkBad(Guid executionId); } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // Microsoft.VisualStudio.QualityTools.LoadTest, Version=16.0.0.0 // C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PrivateAssemblies internal class LoadTestResultsCollector : ICounterProvider { // ...[생략]... public LoadTestResultsCollector(WebTestSuite suite, LoadTestIntervalCallback intervalDataCallback, LoadTestResultsCollectorStatusCallback statusCallback, IControllerContext controllerContext) { // ...[생략]... this.m_suite = suite; // ...[생략]... } public void Initialize(TestRun testRun, string[] agentNames) { // ...[생략]... this.m_licenseManager = new LoadTestUserLicenseManager(this.m_suite.AvailableFeatures, isRemote); try { this.m_licenseManager.CheckForLoadTestExecution(); this.m_licenseManager.CheckForRemoteExecution(); this.m_licenseManager.CheckUserCountForLoadTest((long) this.m_suite.GetMaximumUserLoad()); } catch (LoadTestLicenseViolationException exception4) { this.ProcessException(exception4, this.m_counterWriter > null, false); throw; } // ...[생략]... } internal class LoadTestControllerPlugin : IControllerPlugin { public void Initialize(IControllerContext testContext) { CheapDateTime.Initialize(); this.m_context = testContext; this.m_suite = this.m_context.get_TestElement(); // ...[생략]... } } // ...[생략]... } internal class LoadTestUserLicenseManager { // Fields private LoadTestFeature m_allowedFeatures; private bool m_isRemote; // Methods internal LoadTestUserLicenseManager(LoadTestFeature allowedFeatures, bool isRemote) { this.m_allowedFeatures = allowedFeatures; this.m_isRemote = isRemote; } public void CheckForLoadTestExecution() { if ((this.m_allowedFeatures & 4) == null) { WebTestLoadTrace.Warning("LoadTestResultsCollector.Initialize(): MaxAllowedVUsers is 0."); LoadTestLicenseViolationException exception = new LoadTestLicenseViolationException((string) Messages.WebLoadTestExecution_NoLicenseShort); throw exception; } } public void CheckForRemoteExecution(); public void CheckUserCountForLoadTest(long userLoad); } [CompilerGenerated, TypeIdentifier("A94BC0A0-5884-4D45-8C9E-D9BF9CA0C99A", "Microsoft.VisualStudio.LicenseManagement.Interop._VSSKUEdition")] public enum _VSSKUEdition { VSEDITION_UNKNOWN, VSEDITION_IntShell, VSEDITION_Professional, VSEDITION_Premium, VSEDITION_Ultimate } internal class LicenseHandler // Microsoft.VisualStudio.TestTools.WebStress { // Methods public LicenseHandler() { try { this.InitializeLoadTestLicenseInfo(); } catch (Exception exception) { /* "<a target='tab' href='http://www.sysnet.pe.kr/2/0/11886'>mstest.exe 실행 시 "Visual Studio Enterprise is required to execute the test." 오류</a>" 글에서 설명한 "Microsoft.VisualStudio.Threading" 로딩 예외의 기록이 여기서 발생한 것입니다. */ WebTestLoadTrace.Verbose("LicenseHandler(): Failed to Initialize LoadTestLicense Info: " + exception.ToString()); } } [MethodImpl(MethodImplOptions.NoInlining)] private void InitializeLoadTestLicenseInfo() { IVsLicensingState state = VsLicensingStateInitializationHelpers.CreateIVsLicensingStateForOnlineLicensingSKU(OnlineLicensingSKUs.VisualStudio); _VSSKUEdition vsEdition = (_VSSKUEdition) state.GetVsEdition(); WebTestLoadTrace.Verbose("LicenseHandler.InitializeLoadTestLicenseInfo(): skuEdition: " + vsEdition); this.IsLicensedForLoadTest = vsEdition == _VSSKUEdition.VSEDITION_Ultimate; if (!this.IsLicensedForLoadTest) { WebTestLoadTrace.Error("LicenseHandler.InitializeLoadTestLicenseInfo(): Failed to Initialize LoadTestLicense Info. Sku is not ultimate"); } else { IVsClientRights clientRights = null; state.RefreshClientRights(); state.ValidateClientRights(out clientRights, null); this.UpdateLicensingInformation(clientRights); } } private void UpdateLicensingInformation(IVsClientRights clientRights) { if (clientRights == null) { WebTestLoadTrace.Error("LicenseHandler.UpdateLicensingInformation(): unable to fetch clientRights "); } else if (!clientRights.IsLicenseGood) { WebTestLoadTrace.Error("LicenseHandler.UpdateLicensingInformation(): clientrights' license is not valid."); } else { this.AvailableFeatures = 4; _VSLicenseType licenseType = (_VSLicenseType) clientRights.LicenseType; this.IsLicensedForAllLoadTestFeatures = ((this.IsLicensedForLoadTest && (licenseType != _VSLicenseType.VSLICTYPE_UNKNOWN)) && ((licenseType != _VSLicenseType.VSLICTYPE_TrialPID) && (licenseType != _VSLicenseType.VSLICTYPE_VSExtensionTrial))) && (licenseType != _VSLicenseType.VSLICTYPE_PrereleaseTrialPID); WebTestLoadTrace.Verbose("LicenseHandler.UpdateLicensingInformation(): licenseType: " + licenseType); if (this.IsLicensedForAllLoadTestFeatures) { this.AvailableFeatures |= 8; this.AvailableFeatures |= 0x20; } } } // Properties public LoadTestFeature AvailableFeatures { get; [CompilerGenerated] private set; } public bool IsLicensedForAllLoadTestFeatures { get; [CompilerGenerated] private set; } public bool IsLicensedForLoadTest { get; [CompilerGenerated] private set; } } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PrivateAssemblies\ // Microsoft.VisualStudio.Shell.Connected, Version=16.0.0.0 public enum OnlineLicensingSKUs { VisualStudio, VSWinExpress, VWDExpress, WDExpress } public static class VsLicensingStateInitializationHelpers { // Fields private const string InstallDirValueName = "InstallDir"; // Methods public static IVsLicensingState CreateIVsLicensingStateForOnlineLicensingSKU(OnlineLicensingSKUs sku) { IVsClientRightsTokenCacheManager clientRightsTokenCacheManager = new VsClientRightsTokenCacheManager(); IVsLicensingState state = new VsLicensingState(); if (state != null) { IVsLicensingStateInitialize initialize = (IVsLicensingStateInitialize) state; Guid subscriptionLicenseId = new Guid(sku.LicenseId()); initialize.InitializeForPidAndOnlineLicensing(null, (int) sku.ProductFamily(), ref subscriptionLicenseId, sku.RightsName(), sku.RegistryRoot(), clientRightsTokenCacheManager, null); } return state; } public static IVsLicensingState CreateIVsLicensingStateForPidLicensedSKU(_VSPIDFamily pidFamily); public static string GetVisualStudioInstallPath(); } public static class VsLicensingStateInitializationConstants { // Methods public static string LicenseId(this OnlineLicensingSKUs sku) { switch (sku) { case OnlineLicensingSKUs.VisualStudio: return "715f10eb-9e99-11d2-bfc2-00c04f990235"; case OnlineLicensingSKUs.VSWinExpress: return "E16EC553-041C-403A-A275-958469FCDE74"; case OnlineLicensingSKUs.VWDExpress: return "68CBDD3E-C6BC-4d26-84B6-6411EA3C327A"; case OnlineLicensingSKUs.WDExpress: return "971DCC97-7904-4F36-9744-D21D39B557B3"; } throw new ArgumentException("Invalid sku type for LicenseIds"); } public static _VSPIDFamily ProductFamily(this OnlineLicensingSKUs sku) { switch (sku) { case OnlineLicensingSKUs.VisualStudio: return _VSPIDFamily.VSPID_GROUP_VS; case OnlineLicensingSKUs.VSWinExpress: return _VSPIDFamily.VSPID_GROUP_VSWIN; case OnlineLicensingSKUs.VWDExpress: return _VSPIDFamily.VSPID_GROUP_VWD; case OnlineLicensingSKUs.WDExpress: return _VSPIDFamily.VSPID_GROUP_V1; } throw new ArgumentException("Invalid sku type for ProductFamily"); } public static string RegistryRoot(this OnlineLicensingSKUs sku) => Path.Combine(@"Software\Microsoft", sku.RightsName(), VSGeneralVersion); public static string RightsName(this OnlineLicensingSKUs sku) { switch (sku) { case OnlineLicensingSKUs.VisualStudio: return "VisualStudio"; case OnlineLicensingSKUs.VSWinExpress: return "VSWinExpress"; case OnlineLicensingSKUs.VWDExpress: return "VWDExpress"; case OnlineLicensingSKUs.WDExpress: return "WDExpress"; } throw new ArgumentException("Invalid sku type for RightsName"); } // Properties public static string VSGeneralVersion => "16.0"; } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE // Microsoft.VisualStudio.ProductKeyDialog.dll public class VsLicensingState : IVsLicensingState, IVsLicensingStateInitialize2, IVsLicensingStateInitialize, IVsCurrentVsEdition { // ...[생략]... private VsClientRightsToken GetUserClientRightTokens(VisualStudioLicenseSource source); public int GetVsEdition() => ((int) ProductLicensingUtilities.MapToVSSKUEdition((_VSSKUEdition2) this.CurrentVsEdition)); [AsyncStateMachine(typeof(<InitializeAsync>d__30))] private Task InitializeAsync(JoinableTaskContext joinableTaskContext, int productFamily, bool isSubscriptionAware, Guid subscriptionLicenseId, string subscriptionRightsName, string registryRoot, IVsClientRightsTokenCacheManager vsClientRightsTokenCacheManager, IVsOnlineLicensingManager onlineLicensingManager); public void InitializeForPidAndOnlineLicensing(object joinableTaskContext, int productFamily, ref Guid subscriptionLicenseId, string subscriptionRightsName, string registryRoot, IVsClientRightsTokenCacheManager clientRightsTokenCacheManager, IVsOnlineLicensingManager onlineLicensingManager) { JoinableTaskContext jtc = ((JoinableTaskContext) joinableTaskContext) ?? this.CreateJoinableTaskContext(); Guid subscriptionLicenseIdLocal = subscriptionLicenseId; jtc.Factory.Run(() => this.InitializeForPidAndOnlineLicensingAsync(jtc, productFamily, subscriptionLicenseIdLocal, subscriptionRightsName, registryRoot, clientRightsTokenCacheManager, onlineLicensingManager)); } public Task InitializeForPidAndOnlineLicensingAsync(JoinableTaskContext joinableTaskContext, int productFamily, Guid subscriptionLicenseId, string subscriptionRightsName, string registryRoot, IVsClientRightsTokenCacheManager clientRightsTokenCacheManager, IVsOnlineLicensingManager onlineLicensingManager) => this.InitializeAsync(joinableTaskContext, productFamily, true, subscriptionLicenseId, subscriptionRightsName, registryRoot, clientRightsTokenCacheManager, onlineLicensingManager); public void InitializeForPidLicensingOnly(object joinableTaskContext, int productFamily, IVsOnlineLicensingManager onlineLicensingManager); public Task InitializeForPidLicensingOnlyAsync(JoinableTaskContext joinableTaskContext, int productFamily, IVsOnlineLicensingManager onlineLicensingManager); // ...[생략]... } internal static class ProductLicensingUtilities { // Methods internal static bool EqualsDateTimeMax(DateTimeOffset expirationDate); internal static int GetMPCofCurrentVSInstance(IVsOnlineOperationLogger logger = null); internal static _VSSKUEdition2 GetVSSKUEditionFromSubscriptionFamilyLevel(string subscriptionFamilyLevel); internal static _VSSKUEdition MapToVSSKUEdition(_VSSKUEdition2 skuEdition2) { if (skuEdition2 <= _VSSKUEdition2.VSEDITION2_IntShell) { if (skuEdition2 == _VSSKUEdition2.VSEDITION2_UNKNOWN) { goto Label_0029; } if (skuEdition2 == _VSSKUEdition2.VSEDITION2_IntShell) { return _VSSKUEdition.VSEDITION_IntShell; } goto Label_0031; } if (skuEdition2 != _VSSKUEdition2.VSEDITION2_Community) { if (skuEdition2 == _VSSKUEdition2.VSEDITION2_Professional) { return _VSSKUEdition.VSEDITION_Professional; } if (skuEdition2 == _VSSKUEdition2.VSEDITION2_Ultimate) { return _VSSKUEdition.VSEDITION_Ultimate; } goto Label_0031; } Label_0029: return _VSSKUEdition.VSEDITION_UNKNOWN; Label_0031: return _VSSKUEdition.VSEDITION_UNKNOWN; } internal static string TrimPrefix(this string s, string prefix); } </pre> <br /> <hr style='width: 50%' /><br /> <br /> mstest.exe의 라이선스와 관련해 문제가 발생하면 위의 소스 코드에서 "WebTestLoadTrace"로 남겨지는 로그들을 함께 추적해 보면 원인을 추적할 수 있습니다. 한 가지 위의 소스 코드를 통해 알 수 있었던 재미있는 점은, Ultimate 에디션의 경우 명칭은 사라졌지만 결국 Enterprise의 내부 이름으로 남아 있다는 것입니다.<br /> <br /> 마지막으로, 실제적인 라이선스 체크는 PInvoke를 통한 내부 C/C++ 함수로 호출이 된다는 점!<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8763
(왼쪽의 숫자를 입력해야 합니다.)