diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/AddIn.csproj b/src/AddIns/Misc/Profiler/Frontend/AddIn/AddIn.csproj index 6f7f2f94a1..820606df0c 100644 --- a/src/AddIns/Misc/Profiler/Frontend/AddIn/AddIn.csproj +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/AddIn.csproj @@ -115,6 +115,7 @@ + diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/ICSharpCode.Profiler.AddIn.addin b/src/AddIns/Misc/Profiler/Frontend/AddIn/ICSharpCode.Profiler.AddIn.addin index c60aa8e5a8..f20da49635 100644 --- a/src/AddIns/Misc/Profiler/Frontend/AddIn/ICSharpCode.Profiler.AddIn.addin +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/ICSharpCode.Profiler.AddIn.addin @@ -78,4 +78,8 @@ class = "ICSharpCode.Profiler.AddIn.OptionsPanels.General"/> + + + + diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopyStacktrace.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopyStacktrace.cs index edb099e9fa..d70c76302d 100644 --- a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopyStacktrace.cs +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopyStacktrace.cs @@ -7,12 +7,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Forms; using System.Windows.Shapes; using ICSharpCode.Core; +using ICSharpCode.Profiler.Controller.Queries; using ICSharpCode.Profiler.Controls; namespace ICSharpCode.Profiler.AddIn.Commands @@ -30,14 +32,16 @@ namespace ICSharpCode.Profiler.AddIn.Commands var selectedItem = GetSelectedItems().FirstOrDefault(); if (selectedItem != null) { - StringBuilder data = new StringBuilder(); - - while (selectedItem.Parent != null) { - data.AppendLine(selectedItem.GetSignature()); - selectedItem = selectedItem.Parent; + var node = selectedItem.Node; + var data = new StringBuilder(); + while (node != null && node.NameMapping.Id != 0) { // TODO : Callers returns a "merged node" as a caller, + // is checking for Id == 0 safe??? + data.AppendLine(node.Signature); + node = node.Callers.FirstOrDefault(); // TODO : only takes first path! } - - Clipboard.SetText(data.ToString()); + + if (data.Length > 0) + Clipboard.SetText(data.ToString()); } } } diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/ProfileProject.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/ProfileProject.cs index 6a5c183744..7f4768adf5 100644 --- a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/ProfileProject.cs +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/ProfileProject.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Profiler.AddIn.Commands Directory.CreateDirectory(Path.GetDirectoryName(path)); IProfilingDataWriter writer = new ProfilingDataSQLiteWriter(path); - ProfilerRunner runner = CreateRunner(writer); + ProfilerRunner runner = WindowsProfiler.CreateRunner(writer); if (runner != null) { runner.RunFinished += delegate { @@ -61,32 +61,5 @@ namespace ICSharpCode.Profiler.AddIn.Commands runner.Run(); } } - - static ProfilerRunner CreateRunner(IProfilingDataWriter writer) - { - AbstractProject currentProj = ProjectService.CurrentProject as AbstractProject; - - if (currentProj == null) - return null; - - if (!currentProj.IsStartable) { - if (MessageService.AskQuestion("This project cannot be started. Do you want to profile the solution's StartUp project instead?")) { - currentProj = ProjectService.OpenSolution.StartupProject as AbstractProject; - if (currentProj == null) { - MessageService.ShowError("No startable project was found. Aborting ..."); - return null; - } - } else - return null; - } - if (!File.Exists(currentProj.OutputAssemblyFullPath)) { - MessageService.ShowError("This project cannot be started because the executable file was not found, " + - "please ensure that the project and all its depencies are built correctly!"); - return null; - } - - ProfilerRunner runner = new ProfilerRunner(currentProj.CreateStartInfo(), true, writer); - return runner; - } } } diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/ProfilerRunner.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/ProfilerRunner.cs index e99e0ed710..6cdf9ae545 100644 --- a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/ProfilerRunner.cs +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/ProfilerRunner.cs @@ -11,6 +11,7 @@ using ICSharpCode.Core; using ICSharpCode.Profiler.AddIn.OptionsPanels; using ICSharpCode.Profiler.Controller.Data; using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Profiling; namespace ICSharpCode.Profiler.AddIn { @@ -98,7 +99,7 @@ namespace ICSharpCode.Profiler.AddIn public void Stop() { - throw new NotImplementedException(); + profiler.Stop(); } #region MessageView Management diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/WpfViewer.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/WpfViewer.cs index e49b9596d9..2e953f4d05 100644 --- a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/WpfViewer.cs +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/WpfViewer.cs @@ -29,6 +29,13 @@ namespace ICSharpCode.Profiler.AddIn.Views ProfilerView dataView; OpenedFile file; + /// + /// Returns the ProfilerView of this instance. + /// + public ProfilerView DataView { + get { return dataView; } + } + /// /// The representing the view /// diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/WindowsProfiler.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/WindowsProfiler.cs new file mode 100644 index 0000000000..02ac8dee3a --- /dev/null +++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/WindowsProfiler.cs @@ -0,0 +1,94 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Diagnostics; +using ICSharpCode.Core; +using ICSharpCode.Profiler.Controller.Data; +using ICSharpCode.SharpDevelop.Profiling; +using ICSharpCode.SharpDevelop.Project; +using System.IO; + +namespace ICSharpCode.Profiler.AddIn +{ + /// + /// Description of WindowsProfiler. + /// + public class WindowsProfiler : IProfiler + { + ProfilerRunner runner; + bool isRunning = false; + + public WindowsProfiler() + { + } + + public bool CanProfile(IProject project) + { + return project != null && project.IsStartable; + } + + public void Start(ProcessStartInfo info, string outputPath, Action afterFinishAction) + { + this.runner = new ProfilerRunner(info, true, new ProfilingDataSQLiteWriter(outputPath)); + + if (runner != null) { + runner.RunFinished += delegate { + try { + afterFinishAction(); + } finally { + this.isRunning = false; + } + }; + this.isRunning = true; + runner.Run(); + } + } + + public static ProfilerRunner CreateRunner(IProfilingDataWriter writer) + { + AbstractProject currentProj = ProjectService.CurrentProject as AbstractProject; + + if (currentProj == null) + return null; + + if (!currentProj.IsStartable) { + if (MessageService.AskQuestion("This project cannot be started. Do you want to profile the solution's StartUp project instead?")) { + currentProj = ProjectService.OpenSolution.StartupProject as AbstractProject; + if (currentProj == null) { + MessageService.ShowError("No startable project was found. Aborting ..."); + return null; + } + } else + return null; + } + if (!File.Exists(currentProj.OutputAssemblyFullPath)) { + MessageService.ShowError("This project cannot be started because the executable file was not found, " + + "please ensure that the project and all its depencies are built correctly!"); + return null; + } + + ProfilerRunner runner = new ProfilerRunner(currentProj.CreateStartInfo(), true, writer); + return runner; + } + + public void Dispose() + { + } + + public bool IsRunning { + get { + return this.isRunning; + } + } + + public void Stop() + { + this.runner.Stop(); + } + } +} diff --git a/src/AddIns/Misc/Profiler/Profiler.sln b/src/AddIns/Misc/Profiler/Profiler.sln index 3012acea72..22f56da76f 100644 --- a/src/AddIns/Misc/Profiler/Profiler.sln +++ b/src/AddIns/Misc/Profiler/Profiler.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -# SharpDevelop 3.1.0.3895 +# SharpDevelop 3.1.0.4082 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5147BA25-8362-481D-8CF9-450096595B7A}" ProjectSection(SolutionItems) = preProject TODO.txt = TODO.txt @@ -13,6 +13,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frontend", "Frontend", "{E0 ProjectSection(SolutionItems) = postProject EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls", "Frontend\Controls\Controls.csproj", "{BDA49550-5ED1-4C6B-B648-657B2CACD8E0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddIn", "Frontend\AddIn\AddIn.csproj", "{D294A12D-4B38-4F25-9AA6-3D4A6CE26E7B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkRunner", "Frontend\BenchmarkRunner\BenchmarkRunner.csproj", "{DBEF953E-F7BC-4D54-8A27-B758EC875C49}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gui", "Frontend\Gui\Gui.csproj", "{FF09FBA1-86DA-4D8D-B549-A4FC70FC5AE9}" ProjectSection(ProjectDependencies) = postProject {D294A12D-4B38-4F25-9AA6-3D4A6CE26E7B} = {D294A12D-4B38-4F25-9AA6-3D4A6CE26E7B} @@ -21,25 +27,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gui", "Frontend\Gui\Gui.csp {778BA9AE-EE77-444F-A0C9-D795BB977C1A} = {778BA9AE-EE77-444F-A0C9-D795BB977C1A} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkRunner", "Frontend\BenchmarkRunner\BenchmarkRunner.csproj", "{DBEF953E-F7BC-4D54-8A27-B758EC875C49}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddIn", "Frontend\AddIn\AddIn.csproj", "{D294A12D-4B38-4F25-9AA6-3D4A6CE26E7B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls", "Frontend\Controls\Controls.csproj", "{BDA49550-5ED1-4C6B-B648-657B2CACD8E0}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{791AE00B-AD96-410A-AAA8-957DDD83C57A}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "Tests\Benchmark\Benchmark.csproj", "{F09B6132-5DF9-4E63-BA23-EE82D75CD5B9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnicodeTest", "Tests\UnicodeTest\UnicodeTest.csproj", "{D336926C-6180-4F62-B88D-E366B240127B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "Tests\HelloWorld\HelloWorld.csproj", "{778BA9AE-EE77-444F-A0C9-D795BB977C1A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Profiler.Tests", "Tests\Profiler.Tests\Profiler.Tests.csproj", "{068F9531-5D29-49E0-980E-59982A3A0469}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PauseTest", "Tests\PauseTest\PauseTest.csproj", "{650AEAA0-0678-4A75-A1CC-F46DC4E44D2A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Profiler.Tests", "Tests\Profiler.Tests\Profiler.Tests.csproj", "{068F9531-5D29-49E0-980E-59982A3A0469}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "Tests\HelloWorld\HelloWorld.csproj", "{778BA9AE-EE77-444F-A0C9-D795BB977C1A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnicodeTest", "Tests\UnicodeTest\UnicodeTest.csproj", "{D336926C-6180-4F62-B88D-E366B240127B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "Tests\Benchmark\Benchmark.csproj", "{F09B6132-5DF9-4E63-BA23-EE82D75CD5B9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hook", "Hook\Hook.vcproj", "{68D5EE3B-0C35-4DF1-BD29-6606851A02C1}" EndProject @@ -173,14 +173,14 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {BDA49550-5ED1-4C6B-B648-657B2CACD8E0} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} - {D294A12D-4B38-4F25-9AA6-3D4A6CE26E7B} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} - {DBEF953E-F7BC-4D54-8A27-B758EC875C49} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} {FF09FBA1-86DA-4D8D-B549-A4FC70FC5AE9} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} - {D336926C-6180-4F62-B88D-E366B240127B} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} - {068F9531-5D29-49E0-980E-59982A3A0469} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} - {650AEAA0-0678-4A75-A1CC-F46DC4E44D2A} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} - {778BA9AE-EE77-444F-A0C9-D795BB977C1A} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} + {DBEF953E-F7BC-4D54-8A27-B758EC875C49} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} + {D294A12D-4B38-4F25-9AA6-3D4A6CE26E7B} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} + {BDA49550-5ED1-4C6B-B648-657B2CACD8E0} = {E06867E9-6942-4DB6-89F5-DE0BF56C44DE} {F09B6132-5DF9-4E63-BA23-EE82D75CD5B9} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} + {778BA9AE-EE77-444F-A0C9-D795BB977C1A} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} + {650AEAA0-0678-4A75-A1CC-F46DC4E44D2A} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} + {068F9531-5D29-49E0-980E-59982A3A0469} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} + {D336926C-6180-4F62-B88D-E366B240127B} = {791AE00B-AD96-410A-AAA8-957DDD83C57A} EndGlobalSection EndGlobal diff --git a/src/AddIns/Misc/UnitTesting/Src/RunTestCommands.cs b/src/AddIns/Misc/UnitTesting/Src/RunTestCommands.cs index 6ef1a2be69..948147b3fe 100644 --- a/src/AddIns/Misc/UnitTesting/Src/RunTestCommands.cs +++ b/src/AddIns/Misc/UnitTesting/Src/RunTestCommands.cs @@ -5,11 +5,11 @@ // $Revision$ // +using ICSharpCode.SharpDevelop.Profiling; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; - using ICSharpCode.Core; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Commands; @@ -516,6 +516,52 @@ namespace ICSharpCode.UnitTesting } } + public class RunTestWithProfilerCommand : AbstractRunTestCommand + { + protected override void RunTests(UnitTestApplicationStartHelper helper) + { + TestRunnerCategory.AppendLine(helper.GetCommandLine()); + ProcessStartInfo startInfo = new ProcessStartInfo(helper.UnitTestApplication); + + string path = ProfilerService.GetSessionFileName(helper.Project); + + startInfo.Arguments = helper.GetArguments(); + startInfo.WorkingDirectory = UnitTestApplicationStartHelper.UnitTestApplicationDirectory; + ProfilerService.CurrentProfiler.Start(startInfo, path, delegate { AfterFinish(helper, path); }); + } + + void AfterFinish(UnitTestApplicationStartHelper helper, string path) + { + Action updater = delegate { + FileService.OpenFile(path); + FileProjectItem file = new FileProjectItem(helper.Project, ItemType.Content, "ProfilingSessions\\" + Path.GetFileName(path)); + ProjectService.AddProjectItem(helper.Project, file); + ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView(); + helper.Project.Save(); + }; + + WorkbenchSingleton.SafeThreadCall(updater); + WorkbenchSingleton.SafeThreadAsyncCall(TestsFinished); + } + + public override void Run() + { + if (ProfilerService.IsProfilerLoaded && ProfilerService.CurrentProfiler.IsRunning) { + MessageService.ShowError("Currently there is a profiling session in progress. " + + "Please finish the current session before starting a new one."); + } else { + base.Run(); + } + } + + protected override void OnStop() + { + if (ProfilerService.CurrentProfiler.IsRunning) { + ProfilerService.CurrentProfiler.Stop(); + } + } + } + public class RunAllTestsInPadCommand : RunTestInPadCommand { public override void Run() @@ -529,7 +575,7 @@ namespace ICSharpCode.UnitTesting public class RunProjectTestsInPadCommand : RunTestInPadCommand, ITestTreeView { public override void Run() - { + { Owner = this; base.Run(); } diff --git a/src/AddIns/Misc/UnitTesting/UnitTesting.addin b/src/AddIns/Misc/UnitTesting/UnitTesting.addin index 1d5122737f..757a11b5bc 100644 --- a/src/AddIns/Misc/UnitTesting/UnitTesting.addin +++ b/src/AddIns/Misc/UnitTesting/UnitTesting.addin @@ -85,6 +85,9 @@ label = "${res:ICSharpCode.UnitTesting.RunWithDebugger}" icon = "Icons.16x16.RunProgramIcon" class = "ICSharpCode.UnitTesting.RunTestWithDebuggerCommand"/> + diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index ac78659522..965220700d 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -147,6 +147,9 @@ + + + @@ -760,6 +763,7 @@ ICSharpCode.SharpDevelop.addin + diff --git a/src/Main/Base/Project/Src/Services/Profiler/DefaultProfiler.cs b/src/Main/Base/Project/Src/Services/Profiler/DefaultProfiler.cs new file mode 100644 index 0000000000..096dfd04e3 --- /dev/null +++ b/src/Main/Base/Project/Src/Services/Profiler/DefaultProfiler.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.SharpDevelop.Profiling +{ + public class DefaultProfiler : IProfiler + { + public bool CanProfile(ICSharpCode.SharpDevelop.Project.IProject project) + { + return false; + } + + public void Start(System.Diagnostics.ProcessStartInfo info, string outputPath, Action afterFinishedAction) + { + throw new NotSupportedException(); + } + + public void Dispose() + { + } + + public bool IsRunning { + get { + return false; + } + } + + public void Stop() + { + throw new NotSupportedException(); + } + } +} diff --git a/src/Main/Base/Project/Src/Services/Profiler/IProfiler.cs b/src/Main/Base/Project/Src/Services/Profiler/IProfiler.cs new file mode 100644 index 0000000000..2d15c56350 --- /dev/null +++ b/src/Main/Base/Project/Src/Services/Profiler/IProfiler.cs @@ -0,0 +1,21 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Project; +using System; +using System.Diagnostics; + +namespace ICSharpCode.SharpDevelop.Profiling +{ + public interface IProfiler : IDisposable + { + bool CanProfile(IProject project); + void Start(ProcessStartInfo info, string outputPath, Action afterFinishedAction); + void Stop(); + bool IsRunning { get; } + } +} diff --git a/src/Main/Base/Project/Src/Services/Profiler/ProfilerService.cs b/src/Main/Base/Project/Src/Services/Profiler/ProfilerService.cs new file mode 100644 index 0000000000..e79d95fdd9 --- /dev/null +++ b/src/Main/Base/Project/Src/Services/Profiler/ProfilerService.cs @@ -0,0 +1,74 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Globalization; +using System.IO; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.SharpDevelop.Profiling +{ + public static class ProfilerService + { + static IProfiler currentProfiler; + static IProfiler[] profilers; + + static ProfilerService() + { + profilers = AddInTree.BuildItems("/SharpDevelop/Services/ProfilerService/Profiler", null, false).ToArray(); + } + + public static bool IsProfilerLoaded + { + get { + return currentProfiler != null; + } + } + + static IProfiler GetCompatibleProfiler() + { + IProject project = null; + if (ProjectService.OpenSolution != null) + project = ProjectService.OpenSolution.StartupProject; + foreach (var p in profilers) { + if (p != null && p.CanProfile(project)) + return p; + } + return new DefaultProfiler(); + } + + public static IProfiler CurrentProfiler { + get { + if (currentProfiler == null) { + currentProfiler = GetCompatibleProfiler(); + } + + return currentProfiler; + } + } + + public static string GetSessionFileName(IProject project) + { + AbstractProject currentProj = ProjectService.CurrentProject as AbstractProject; + + if (currentProj == null) + throw new InvalidOperationException("Can not profile project"); + + string filePart = @"ProfilingSessions\Session" + + DateTime.Now.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture) + + ".sdps"; + + string path = Path.Combine(currentProj.Directory, filePart); + + Directory.CreateDirectory(Path.GetDirectoryName(path)); + + return path; + } + } +}