diff --git a/indra/llcommon/FSTracyClient.cpp b/indra/llcommon/FSTracyClient.cpp
index 1b9a86eb5d..d40c042113 100644
--- a/indra/llcommon/FSTracyClient.cpp
+++ b/indra/llcommon/FSTracyClient.cpp
@@ -14,6 +14,15 @@
#include "common/TracySystem.cpp"
#ifdef TRACY_ENABLE
+// are we actively profiling?
+// At some point this should move to fsprofiler.cpp to correspond with the headerfile
+#ifdef TRACY_ENABLE
+namespace FSProfiler
+{
+ bool active{false};
+}
+#endif
+//
#ifdef _MSC_VER
# pragma warning(push, 0)
diff --git a/indra/llcommon/fsprofiler.h b/indra/llcommon/fsprofiler.h
new file mode 100644
index 0000000000..41ffa6a17f
--- /dev/null
+++ b/indra/llcommon/fsprofiler.h
@@ -0,0 +1,32 @@
+#pragma once
+#ifndef FS_PROFILER_H_INCLUDED
+#define FS_PROFILER_H_INCLUDED
+
+// define a simple set of empty macros that allow us to build without the Tracy profiler installed in 3p
+// this is similar to the profiler abstraction used by LL but as they have no plans to release that any time soon we'll replace it
+// Just a minimal set at the moment will add locks/gpu/memory and other stuff later
+
+#ifdef TRACY_ENABLE
+#include "Tracy.hpp"
+namespace FSProfiler
+{
+ extern bool active;
+}
+
+#define FSZone ZoneNamed( ___tracy_scoped_zone, FSProfiler::active)
+#define FSZoneN( name ) ZoneNamedN( ___tracy_scoped_zone, name, FSProfiler::active)
+#define FSZoneC(color) ZoneNamedC( ___tracy_scoped_zone, color, FSProfiler::active)
+#define FSZoneNC(name, color) ZoneNamedNC( ___tracy_scoped_zone, name, color, FSProfiler::active)
+#define FSPlot( name, value ) TracyPlot( name, value)
+#define FSFrameMark FrameMark
+
+#else
+
+#define FSZone
+#define FSZoneN( name )
+#define FSZoneC(color)
+#define FSZoneNC(name, color)
+#define FSPlot( name, value )
+#define FSFrameMark
+#endif // TRACY_ENABLE
+#endif
\ No newline at end of file
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index ac3e260fb1..4f6afd17fd 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -54,15 +54,7 @@
#else
#error "architecture not supported"
#endif
-// are we actively profiling?
-#ifdef TRACY_ENABLE
-namespace LLTrace
-{
- bool active{false};
-}
-//
-#endif
namespace LLTrace
{
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index e0df4f5277..70c0735f35 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -41,21 +41,15 @@
// Add Tracy profiler support
// #define LL_RECORD_BLOCK_TIME(timer_stat) \
// const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
+#include "fsprofiler.h"
#ifdef TRACY_ENABLE
-
-#include "Tracy.hpp"
-
-namespace LLTrace
-{
- extern bool active;
-}
// #undef TRACY_NO_FASTTIMERS // Uncomment if you want FASTTIMERS as well.
#ifdef TRACY_NO_FASTTIMERS
#define LL_RECORD_BLOCK_TIME(timer_stat) \
-ZoneNamedN( ___tracy_scoped_zone, #timer_stat , LLTrace::active);
+FSZoneN( #timer_stat );
#else // TRACY_NO_FASTTIMERS
#define LL_RECORD_BLOCK_TIME(timer_stat) \
-ZoneNamedN( ___tracy_scoped_zone, #timer_stat , LLTrace::active); \
+FSZoneN( #timer_stat ); \
const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
#endif // TRACY_NO_FASTTIMERS
#else // TRACY_ENABLE
diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index 8e5bc6406d..4b2b28af80 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -33,8 +33,7 @@
#include "llfilesystem.h"
#include "llfasttimer.h"
#include "lldiskcache.h"
-
-#define FSZoneScoped ZoneNamedC( ___tracy_scoped_zone, tracy::Color::Gold, LLTrace::active);
+#include "fsprofiler.h"
const S32 LLFileSystem::READ = 0x00000001;
const S32 LLFileSystem::WRITE = 0x00000002;
@@ -59,7 +58,7 @@ LLFileSystem::~LLFileSystem()
// static
bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
std::string id_str;
file_id.toString(id_str);
const std::string extra_info = "";
@@ -88,7 +87,7 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil
bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error /*= 0*/)
//
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
std::string id_str;
file_id.toString(id_str);
const std::string extra_info = "";
@@ -106,7 +105,8 @@ bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType fi
bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type,
const LLUUID& new_file_id, const LLAssetType::EType new_file_type)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
std::string old_id_str;
old_file_id.toString(old_id_str);
const std::string extra_info = "";
@@ -137,7 +137,8 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
// static
S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
std::string id_str;
file_id.toString(id_str);
const std::string extra_info = "";
@@ -163,7 +164,8 @@ S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType fi
BOOL LLFileSystem::read(U8* buffer, S32 bytes)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
BOOL success = TRUE;
std::string id;
@@ -222,19 +224,22 @@ BOOL LLFileSystem::read(U8* buffer, S32 bytes)
S32 LLFileSystem::getLastBytesRead()
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
return mBytesRead;
}
BOOL LLFileSystem::eof()
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
return mPosition >= getSize();
}
BOOL LLFileSystem::write(const U8* buffer, S32 bytes)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
std::string id_str;
mFileID.toString(id_str);
const std::string extra_info = "";
@@ -344,7 +349,8 @@ BOOL LLFileSystem::write(const U8* buffer, S32 bytes)
BOOL LLFileSystem::seek(S32 offset, S32 origin)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
if (-1 == origin)
{
origin = mPosition;
@@ -375,26 +381,30 @@ BOOL LLFileSystem::seek(S32 offset, S32 origin)
S32 LLFileSystem::tell() const
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
return mPosition;
}
S32 LLFileSystem::getSize()
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
return LLFileSystem::getFileSize(mFileID, mFileType);
}
S32 LLFileSystem::getMaxSize()
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
// offer up a huge size since we don't care what the max is
return INT_MAX;
}
BOOL LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_type)
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
LLFileSystem::renameFile(mFileID, mFileType, new_id, new_type);
mFileID = new_id;
@@ -405,7 +415,8 @@ BOOL LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_typ
BOOL LLFileSystem::remove()
{
- FSZoneScoped;
+ FSZoneC(tracy::Color::Gold);
+;
LLFileSystem::removeFile(mFileID, mFileType);
return TRUE;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 8b42cc7035..f16570c2de 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -282,6 +282,8 @@
#include "fsradar.h"
#include "fsassetblacklist.h"
+#include "fsprofiler.h" // Tracy profiler support
+
#if (LL_LINUX || LL_SOLARIS) && LL_GTK
#include "glib.h"
#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
@@ -1653,17 +1655,19 @@ bool LLAppViewer::doFrame()
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD newFrame;
// Tracy enabling
+#ifdef TRACY_ENABLE
static bool one_time{false};
static LLCachedControl tracy_enable_when_connected(gSavedSettings, "FSTracyEnableWhenConnected");
if( !one_time && (gFrameCount % 10 == 0) )
{
- if(!LLTrace::active && tracy_enable_when_connected && TracyIsConnected)
+ if(!FSProfiler::active && tracy_enable_when_connected && TracyIsConnected)
{
- LLTrace::active = true;
+ FSProfiler::active = true;
one_time=true; // prevent reset race if we disable manually.
LL_INFOS() << "Tracy profiler or collector connected" << LL_ENDL;
}
}
+#endif
//
// MaxFPS Viewer-Chui merge error
LLTimer periodicRenderingTimer;
@@ -1965,7 +1969,7 @@ bool LLAppViewer::doFrame()
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
- FrameMark; // Tracy support delineate Frame
+ FSFrameMark; // Tracy support delineate Frame
return ! LLApp::isRunning();
}
diff --git a/indra/tools/vstool/DispatchUtility.cs b/indra/tools/vstool/DispatchUtility.cs
deleted file mode 100644
index 6056ac55a1..0000000000
--- a/indra/tools/vstool/DispatchUtility.cs
+++ /dev/null
@@ -1,271 +0,0 @@
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.Reflection;
-using System.Security.Permissions;
-
-#endregion
-
-namespace TestDispatchUtility
-{
- ///
- /// Provides helper methods for working with COM IDispatch objects that have a registered type library.
- ///
- public static class DispatchUtility
- {
- #region Private Constants
-
- private const int S_OK = 0; //From WinError.h
- private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800
-
- #endregion
-
- #region Public Methods
-
- ///
- /// Gets whether the specified object implements IDispatch.
- ///
- /// An object to check.
- /// True if the object implements IDispatch. False otherwise.
- public static bool ImplementsIDispatch(object obj)
- {
- bool result = obj is IDispatchInfo;
- return result;
- }
-
- ///
- /// Gets a Type that can be used with reflection.
- ///
- /// An object that implements IDispatch.
- /// Whether an exception should be thrown if a Type can't be obtained.
- /// A .NET Type that can be used with reflection.
- /// If doesn't implement IDispatch.
- [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
- public static Type GetType(object obj, bool throwIfNotFound)
- {
- RequireReference(obj, "obj");
- Type result = GetType((IDispatchInfo)obj, throwIfNotFound);
- return result;
- }
-
- ///
- /// Tries to get the DISPID for the requested member name.
- ///
- /// An object that implements IDispatch.
- /// The name of a member to lookup.
- /// If the method returns true, this holds the DISPID on output.
- /// If the method returns false, this value should be ignored.
- /// True if the member was found and resolved to a DISPID. False otherwise.
- /// If doesn't implement IDispatch.
- [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
- public static bool TryGetDispId(object obj, string name, out int dispId)
- {
- RequireReference(obj, "obj");
- bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId);
- return result;
- }
-
- ///
- /// Invokes a member by DISPID.
- ///
- /// An object that implements IDispatch.
- /// The DISPID of a member. This can be obtained using
- /// .
- /// The arguments to pass to the member.
- /// The member's return value.
- ///
- /// This can invoke a method or a property get accessor.
- ///
- public static object Invoke(object obj, int dispId, object[] args)
- {
- string memberName = "[DispId=" + dispId + "]";
- object result = Invoke(obj, memberName, args);
- return result;
- }
-
- ///
- /// Invokes a member by name.
- ///
- /// An object.
- /// The name of the member to invoke.
- /// The arguments to pass to the member.
- /// The member's return value.
- ///
- /// This can invoke a method or a property get accessor.
- ///
- public static object Invoke(object obj, string memberName, object[] args)
- {
- RequireReference(obj, "obj");
- Type type = obj.GetType();
- object result = type.InvokeMember(memberName, BindingFlags.InvokeMethod | BindingFlags.GetProperty,
- null, obj, args, null);
- return result;
- }
-
- #endregion
-
- #region Private Methods
-
- ///
- /// Requires that the value is non-null.
- ///
- /// The type of the value.
- /// The value to check.
- /// The name of the value.
- private static void RequireReference(T value, string name) where T : class
- {
- if (value == null)
- {
- throw new ArgumentNullException(name);
- }
- }
-
- ///
- /// Gets a Type that can be used with reflection.
- ///
- /// An object that implements IDispatch.
- /// Whether an exception should be thrown if a Type can't be obtained.
- /// A .NET Type that can be used with reflection.
- private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound)
- {
- RequireReference(dispatch, "dispatch");
-
- Type result = null;
- int typeInfoCount;
- int hr = dispatch.GetTypeInfoCount(out typeInfoCount);
- if (hr == S_OK && typeInfoCount > 0)
- {
- // Type info isn't usually culture-aware for IDispatch, so we might as well pass
- // the default locale instead of looking up the current thread's LCID each time
- // (via CultureInfo.CurrentCulture.LCID).
- dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result);
- }
-
- if (result == null && throwIfNotFound)
- {
- // If the GetTypeInfoCount called failed, throw an exception for that.
- Marshal.ThrowExceptionForHR(hr);
-
- // Otherwise, throw the same exception that Type.GetType would throw.
- throw new TypeLoadException();
- }
-
- return result;
- }
-
- ///
- /// Tries to get the DISPID for the requested member name.
- ///
- /// An object that implements IDispatch.
- /// The name of a member to lookup.
- /// If the method returns true, this holds the DISPID on output.
- /// If the method returns false, this value should be ignored.
- /// True if the member was found and resolved to a DISPID. False otherwise.
- private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId)
- {
- RequireReference(dispatch, "dispatch");
- RequireReference(name, "name");
-
- bool result = false;
-
- // Members names aren't usually culture-aware for IDispatch, so we might as well
- // pass the default locale instead of looking up the current thread's LCID each time
- // (via CultureInfo.CurrentCulture.LCID).
- Guid iidNull = Guid.Empty;
- int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId);
-
- const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h
- const int DISPID_UNKNOWN = -1; //From OAIdl.idl
- if (hr == S_OK)
- {
- result = true;
- }
- else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN)
- {
- // This is the only supported "error" case because it means IDispatch
- // is saying it doesn't know the member we asked about.
- result = false;
- }
- else
- {
- // The other documented result codes are all errors.
- Marshal.ThrowExceptionForHR(hr);
- }
-
- return result;
- }
-
- #endregion
-
- #region Private Interfaces
-
- ///
- /// A partial declaration of IDispatch used to lookup Type information and DISPIDs.
- ///
- ///
- /// This interface only declares the first three methods of IDispatch. It omits the
- /// fourth method (Invoke) because there are already plenty of ways to do dynamic
- /// invocation in .NET. But the first three methods provide dynamic type metadata
- /// discovery, which .NET doesn't provide normally if you have a System.__ComObject
- /// RCW instead of a strongly-typed RCW.
- ///
- /// Note: The original declaration of IDispatch is in OAIdl.idl.
- ///
- [ComImport]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- [Guid("00020400-0000-0000-C000-000000000046")]
- private interface IDispatchInfo
- {
- ///
- /// Gets the number of Types that the object provides (0 or 1).
- ///
- /// Returns 0 or 1 for the number of Types provided by .
- ///
- /// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85)
- ///
- [PreserveSig]
- int GetTypeInfoCount(out int typeInfoCount);
-
- ///
- /// Gets the Type information for an object if returned 1.
- ///
- /// Must be 0.
- /// Typically, LOCALE_SYSTEM_DEFAULT (2048).
- /// Returns the object's Type information.
- ///
- /// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85)
- ///
- void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
- MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);
-
- ///
- /// Gets the DISPID of the specified member name.
- ///
- /// Must be IID_NULL. Pass a copy of Guid.Empty.
- /// The name of the member to look up.
- /// Must be 1.
- /// Typically, LOCALE_SYSTEM_DEFAULT (2048).
- /// If a member with the requested
- /// is found, this returns its DISPID and the method's return value is 0.
- /// If the method returns a non-zero value, then this parameter's output value is
- /// undefined.
- /// Zero for success. Non-zero for failure.
- ///
- /// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85)
- ///
- [PreserveSig]
- int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId);
-
- // NOTE: The real IDispatch also has an Invoke method next, but we don't need it.
- // We can invoke methods using .NET's Type.InvokeMember method with the special
- // [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo
- // and invoke methods on that through reflection.
- // Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx
- }
-
- #endregion
- }
-}
diff --git a/indra/tools/vstool/README.txt b/indra/tools/vstool/README.txt
deleted file mode 100644
index e419180031..0000000000
--- a/indra/tools/vstool/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-VSTool is a command line utility to manipulate VisualStudio settings.
-
-The windows cmake project configuration uses VSTool.exe
-
-A handy upgrade:
- figure out how to make cmake build this csharp app
- - or write the app using script (jscript?!?) so it doesn't need to be built.
-
-
diff --git a/indra/tools/vstool/VSTool.csproj b/indra/tools/vstool/VSTool.csproj
deleted file mode 100755
index 7f431e85c7..0000000000
--- a/indra/tools/vstool/VSTool.csproj
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
- Local
- 8.0.50727
- 2.0
- {96943E2D-1373-4617-A117-D0F997A94919}
- Debug
- AnyCPU
-
-
-
-
- VSTool
-
-
- JScript
- Grid
- IE50
- false
- Exe
- VSTool
- Always
- VSTool.VSToolMain
-
-
-
-
- v2.0
- 2.0
-
-
- .\
- false
- 285212672
- false
-
-
- DEBUG;TRACE
-
-
- true
- 4096
- false
-
-
- false
- false
- false
- false
- 4
- full
- prompt
-
-
- .\
- false
- 285212672
- false
-
-
- TRACE
-
-
- false
- 4096
- false
-
-
- true
- false
- false
- false
- 4
- none
- prompt
-
-
-
- System
-
-
- System.Data
-
-
-
-
- Code
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/indra/tools/vstool/VSTool.exe b/indra/tools/vstool/VSTool.exe
deleted file mode 100755
index 751540413a..0000000000
Binary files a/indra/tools/vstool/VSTool.exe and /dev/null differ
diff --git a/indra/tools/vstool/VSTool.sln b/indra/tools/vstool/VSTool.sln
deleted file mode 100755
index 21e3d75971..0000000000
--- a/indra/tools/vstool/VSTool.sln
+++ /dev/null
@@ -1,19 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/indra/tools/vstool/app.config b/indra/tools/vstool/app.config
deleted file mode 100644
index 8494f728ff..0000000000
--- a/indra/tools/vstool/app.config
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/indra/tools/vstool/main.cs b/indra/tools/vstool/main.cs
deleted file mode 100755
index 1d6b2f14d1..0000000000
--- a/indra/tools/vstool/main.cs
+++ /dev/null
@@ -1,733 +0,0 @@
-// Code about getting running instances visual studio
-// was borrowed from
-// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx
-
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using Microsoft.CSharp;
-
-namespace VSTool
-{
- // The MessageFilter class comes from:
- // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx
- // It allows vstool to get timing error messages from
- // visualstudio and handle them.
- public class MessageFilter : IOleMessageFilter
- {
- //
- // Class containing the IOleMessageFilter
- // thread error-handling functions.
-
- // Start the filter.
- public static void Register()
- {
- IOleMessageFilter newFilter = new MessageFilter();
- IOleMessageFilter oldFilter = null;
- CoRegisterMessageFilter(newFilter, out oldFilter);
- }
-
- // Done with the filter, close it.
- public static void Revoke()
- {
- IOleMessageFilter oldFilter = null;
- CoRegisterMessageFilter(null, out oldFilter);
- }
-
- //
- // IOleMessageFilter functions.
- // Handle incoming thread requests.
- int IOleMessageFilter.HandleInComingCall(int dwCallType,
- System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
- lpInterfaceInfo)
- {
- //Return the flag SERVERCALL_ISHANDLED.
- return 0;
- }
-
- // Thread call was rejected, so try again.
- int IOleMessageFilter.RetryRejectedCall(System.IntPtr
- hTaskCallee, int dwTickCount, int dwRejectType)
- {
- if (dwRejectType == 2)
- // flag = SERVERCALL_RETRYLATER.
- {
- // Retry the thread call immediately if return >=0 &
- // <100.
- return 99;
- }
- // Too busy; cancel call.
- return -1;
- }
-
- int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
- int dwTickCount, int dwPendingType)
- {
- //Return the flag PENDINGMSG_WAITDEFPROCESS.
- return 2;
- }
-
- // Implement the IOleMessageFilter interface.
- [DllImport("Ole32.dll")]
- private static extern int
- CoRegisterMessageFilter(IOleMessageFilter newFilter, out
- IOleMessageFilter oldFilter);
- }
-
- [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
- InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
- interface IOleMessageFilter
- {
- [PreserveSig]
- int HandleInComingCall(
- int dwCallType,
- IntPtr hTaskCaller,
- int dwTickCount,
- IntPtr lpInterfaceInfo);
-
- [PreserveSig]
- int RetryRejectedCall(
- IntPtr hTaskCallee,
- int dwTickCount,
- int dwRejectType);
-
- [PreserveSig]
- int MessagePending(
- IntPtr hTaskCallee,
- int dwTickCount,
- int dwPendingType);
- }
-
- class ViaCOM
- {
- public static object GetProperty(object from_obj, string prop_name)
- {
- try
- {
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- prop_name,
- BindingFlags.GetProperty, null,
- from_obj,
- null);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error getting property: \"{0}\"", prop_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
-
- public static object SetProperty(object from_obj, string prop_name, object new_value)
- {
- try
- {
- object[] args = { new_value };
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- prop_name,
- BindingFlags.DeclaredOnly |
- BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.SetProperty,
- null,
- from_obj,
- args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error setting property: \"{0}\"", prop_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
-
- public static object CallMethod(object from_obj, string method_name, params object[] args)
- {
- try
- {
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- method_name,
- BindingFlags.DeclaredOnly |
- BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.InvokeMethod,
- null,
- from_obj,
- args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error calling method \"{0}\"", method_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
- };
-
- ///
- /// The main entry point class for VSTool.
- ///
- class VSToolMain
- {
- #region Interop imports
- [DllImport("ole32.dll")]
- public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
-
- [DllImport("ole32.dll")]
- public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
- #endregion
-
- static System.Boolean ignore_case = true;
-
- static string solution_name = null;
- static bool use_new_vs = false;
- static Hashtable projectDict = new Hashtable();
- static string startup_project = null;
- static string config = null;
-
- static object dte = null;
- static object solution = null;
-
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static int Main(string[] args)
- {
- int retVal = 0;
- bool need_save = false;
-
- try
- {
- parse_command_line(args);
-
- Console.WriteLine("Editing solution: {0}", solution_name);
-
- bool found_open_solution = GetDTEAndSolution();
-
- if (dte == null || solution == null)
- {
- retVal = 1;
- }
- else
- {
- MessageFilter.Register();
-
- // Walk through all of the projects in the solution
- // and list the type of each project.
- foreach (DictionaryEntry p in projectDict)
- {
- string project_name = (string)p.Key;
- string working_dir = (string)p.Value;
- if (SetProjectWorkingDir(solution, project_name, working_dir))
- {
- need_save = true;
- }
- }
-
- if (config != null)
- {
- need_save = SetActiveConfig(config);
- }
-
- if (startup_project != null)
- {
- need_save = SetStartupProject(startup_project);
- }
-
- if (need_save)
- {
- if (found_open_solution == false)
- {
- ViaCOM.CallMethod(solution, "Close", null);
- }
- }
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- retVal = 1;
- }
- finally
- {
- if (solution != null)
- {
- Marshal.ReleaseComObject(solution);
- solution = null;
- }
-
- if (dte != null)
- {
- Marshal.ReleaseComObject(dte);
- dte = null;
- }
-
- MessageFilter.Revoke();
- }
- return retVal;
- }
-
- public static bool parse_command_line(string[] args)
- {
- string options_desc =
- "--solution : MSVC solution name. (required)\n" +
- "--use_new_vs : Ignore running versions of visual studio.\n" +
- "--workingdir : Set working dir of a VC project.\n" +
- "--config : Set the active config for the solution.\n" +
- "--startup : Set the startup project for the solution.\n";
-
- try
- {
- // Command line param parsing loop.
- int i = 0;
- for (; i < args.Length; ++i)
- {
- if ("--solution" == args[i])
- {
- if (solution_name != null)
- {
- throw new ApplicationException("Found second --solution option");
- }
- solution_name = args[++i];
- }
- else if ("--use_new_vs" == args[i])
- {
- use_new_vs = true;
- }
-
- else if ("--workingdir" == args[i])
- {
- string project_name = args[++i];
- string working_dir = args[++i];
- projectDict.Add(project_name, working_dir);
- }
- else if ("--config" == args[i])
- {
- if (config != null)
- {
- throw new ApplicationException("Found second --config option");
- }
- config = args[++i];
- }
- else if ("--startup" == args[i])
- {
- if (startup_project != null)
- {
- throw new ApplicationException("Found second --startup option");
- }
- startup_project = args[++i];
- }
- else
- {
- throw new ApplicationException("Found unrecognized token on command line: " + args[i]);
- }
- }
-
- if (solution_name == null)
- {
- throw new ApplicationException("The --solution option is required.");
- }
- }
- catch(ApplicationException e)
- {
-
- Console.WriteLine("Oops! " + e.Message);
- Console.Write("Command line:");
- foreach (string arg in args)
- {
- Console.Write(" " + arg);
- }
- Console.Write("\n\n");
- Console.WriteLine("VSTool command line usage");
- Console.Write(options_desc);
- throw e;
- }
- return true;
- }
-
- public static bool GetDTEAndSolution()
- {
- bool found_open_solution = true;
-
- Console.WriteLine("Looking for existing VisualStudio instance...");
-
- // Get an instance of the currently running Visual Studio .NET IDE.
- // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1");
- string full_solution_name = System.IO.Path.GetFullPath(solution_name);
- if (false == use_new_vs)
- {
- dte = GetIDEInstance(full_solution_name);
- }
-
- if (dte == null)
- {
- try
- {
- Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance...");
- Console.WriteLine(" Reading .sln file version...");
- string version = GetSolutionVersion(full_solution_name);
-
- Console.WriteLine(" Using version: {0}...", version);
- string progid = GetVSProgID(version);
-
- Type objType = Type.GetTypeFromProgID(progid);
- dte = System.Activator.CreateInstance(objType);
- Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name);
-
- solution = ViaCOM.GetProperty(dte, "Solution");
- object[] openArgs = { full_solution_name };
- ViaCOM.CallMethod(solution, "Open", openArgs);
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Console.WriteLine("Quitting do to error opening: {0}", full_solution_name);
- solution = null;
- dte = null;
- return found_open_solution;
- }
- found_open_solution = false;
- }
-
- if (solution == null)
- {
- solution = ViaCOM.GetProperty(dte, "Solution");
- }
-
- return found_open_solution;
- }
-
- ///
- /// Get the DTE object for the instance of Visual Studio IDE that has
- /// the specified solution open.
- ///
- /// The absolute filename of the solution
- /// Corresponding DTE object or null if no such IDE is running
- public static object GetIDEInstance( string solutionFile )
- {
- Hashtable runningInstances = GetIDEInstances( true );
- IDictionaryEnumerator enumerator = runningInstances.GetEnumerator();
-
- while ( enumerator.MoveNext() )
- {
- try
- {
- object ide = enumerator.Value;
- if (ide != null)
- {
- object sol = ViaCOM.GetProperty(ide, "Solution");
- if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case))
- {
- return ide;
- }
- }
- }
- catch{}
- }
-
- return null;
- }
-
- ///
- /// Get a table of the currently running instances of the Visual Studio .NET IDE.
- ///
- /// Only return instances that have opened a solution
- /// A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object
- public static Hashtable GetIDEInstances( bool openSolutionsOnly )
- {
- Hashtable runningIDEInstances = new Hashtable();
- Hashtable runningObjects = GetRunningObjectTable();
-
- IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
- while ( rotEnumerator.MoveNext() )
- {
- string candidateName = (string) rotEnumerator.Key;
- if (!candidateName.StartsWith("!VisualStudio.DTE"))
- continue;
-
- object ide = rotEnumerator.Value;
- if (ide == null)
- continue;
-
- if (openSolutionsOnly)
- {
- try
- {
- object sol = ViaCOM.GetProperty(ide, "Solution");
- string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName");
- if (solutionFile != String.Empty)
- {
- runningIDEInstances[ candidateName ] = ide;
- }
- }
- catch {}
- }
- else
- {
- runningIDEInstances[ candidateName ] = ide;
- }
- }
- return runningIDEInstances;
- }
-
- ///
- /// Get a snapshot of the running object table (ROT).
- ///
- /// A hashtable mapping the name of the object in the ROT to the corresponding object
- [STAThread]
- public static Hashtable GetRunningObjectTable()
- {
- Hashtable result = new Hashtable();
-
- int numFetched = 0;
- IRunningObjectTable runningObjectTable;
- IEnumMoniker monikerEnumerator;
- IMoniker[] monikers = new IMoniker[1];
-
- GetRunningObjectTable(0, out runningObjectTable);
- runningObjectTable.EnumRunning(out monikerEnumerator);
- monikerEnumerator.Reset();
-
- while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0)
- {
- IBindCtx ctx;
- CreateBindCtx(0, out ctx);
-
- string runningObjectName;
- monikers[0].GetDisplayName(ctx, null, out runningObjectName);
-
- object runningObjectVal;
- runningObjectTable.GetObject( monikers[0], out runningObjectVal);
-
- result[ runningObjectName ] = runningObjectVal;
- }
-
- return result;
- }
-
- public static string GetSolutionVersion(string solutionFullFileName)
- {
- string version;
- System.IO.StreamReader solutionStreamReader = null;
- string firstLine;
- string format;
-
- try
- {
- solutionStreamReader = new System.IO.StreamReader(solutionFullFileName);
- do
- {
- firstLine = solutionStreamReader.ReadLine();
- }
- while (firstLine == "");
-
- format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim();
-
- switch(format)
- {
- case "7.00":
- version = "VC70";
- break;
-
- case "8.00":
- version = "VC71";
- break;
-
- case "9.00":
- version = "VC80";
- break;
-
- case "10.00":
- version = "VC90";
- break;
-
- case "11.00":
- version = "VC100";
- break;
-
- case "12.00":
- version = "VC150";
- break;
-
- default:
- throw new ApplicationException("Unknown .sln version: " + format);
- }
- }
- finally
- {
- if(solutionStreamReader != null)
- {
- solutionStreamReader.Close();
- }
- }
-
- return version;
- }
-
- public static string GetVSProgID(string version)
- {
- string progid = null;
- switch(version)
- {
- case "VC70":
- progid = "VisualStudio.DTE.7";
- break;
-
- case "VC71":
- progid = "VisualStudio.DTE.7.1";
- break;
-
- case "VC80":
- progid = "VisualStudio.DTE.8.0";
- break;
-
- case "VC90":
- progid = "VisualStudio.DTE.9.0";
- break;
-
- case "VC100":
- progid = "VisualStudio.DTE.10.0";
- break;
-
- case "VC120":
- progid = "VisualStudio.DTE.12.0";
- break;
-
- case "VC150":
- progid = "VisualStudio.DTE.15.0";
- break;
-
- default:
- throw new ApplicationException("Can't handle VS version: " + version);
- }
-
- return progid;
- }
-
- public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir)
- {
- bool made_change = false;
- Console.WriteLine("Looking for project {0}...", project_name);
- try
- {
- object prjs = ViaCOM.GetProperty(sol, "Projects");
- object count = ViaCOM.GetProperty(prjs, "Count");
- for(int i = 1; i <= (int)count; ++i)
- {
- object[] prjItemArgs = { (object)i };
- object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs);
- string name = (string)ViaCOM.GetProperty(prj, "Name");
- if (0 == string.Compare(name, project_name, ignore_case))
- {
- Console.WriteLine("Found project: {0}", project_name);
- Console.WriteLine("Setting working directory");
-
- string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName");
- Console.WriteLine(full_project_name);
-
- // *NOTE:Mani Thanks to incompatibilities between different versions of the
- // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to
- // the VCProjectEngine types from a different version than the one built
- // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built
- // in VS 8.0. To avoid this problem, we can use the com object interfaces directly,
- // without the type casting. Its tedious code, but it seems to work.
-
- // oCfgs should be assigned to a 'Project.Configurations' collection.
- object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations");
-
- // oCount will be assigned to the number of configs present in oCfgs.
- object oCount = ViaCOM.GetProperty(oCfgs, "Count");
-
- for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex)
- {
- object[] itemArgs = {(object)cfgIndex};
- object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs);
- object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings");
- ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir);
- }
-
- break;
- }
- }
- made_change = true;
- }
- catch( Exception e )
- {
- Console.WriteLine(e.Message);
- Console.WriteLine("Failed to set working dir for project, {0}.", project_name);
- }
-
- return made_change;
- }
-
- public static bool SetStartupProject(string startup_project)
- {
- bool result = false;
- try
- {
- // You need the 'unique name of the project to set StartupProjects.
- // find the project by generic name.
- Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project);
- object prjs = ViaCOM.GetProperty(solution, "Projects");
- object count = ViaCOM.GetProperty(prjs, "Count");
- for (int i = 1; i <= (int)count; ++i)
- {
- object[] itemArgs = { (object)i };
- object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs);
- object prjName = ViaCOM.GetProperty(prj, "Name");
- if (0 == string.Compare((string)prjName, startup_project, ignore_case))
- {
- object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
- ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName"));
- Console.WriteLine(" Success!");
- result = true;
- break;
- }
- }
-
- if (result == false)
- {
- Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project);
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(" Failed to set the startup project!");
- Console.WriteLine(e.Message);
- }
- return result;
- }
-
- public static bool SetActiveConfig(string config)
- {
- bool result = false;
- try
- {
- Console.WriteLine("Trying to set active config to \"{0}\"", config);
- object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
- object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations");
- object[] itemArgs = { (object)config };
- object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs);
- ViaCOM.CallMethod(solCfg, "Activate", null);
- Console.WriteLine(" Success!");
- result = true;
- }
- catch (Exception e)
- {
- Console.WriteLine(" Failed to set \"{0}\" as the active config.", config);
- Console.WriteLine(e.Message);
- }
- return result;
- }
- }
-}