Debug Sound Forge example

mischke wrote on 10/19/2016, 6:14 AM

Hi guys,

Just wanted to share my hack to get debugging working in Visual Studio for Sound Forge.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using SoundForge;
using EnvDTE;
using Process = System.Diagnostics.Process;

#region readme

// BASIC C# Solution
// Demonstrates how to create a C# DLL that can be run from Sound Forge
// (scripting available in Sound Forge 8.0 or higher)
//
// Last Modified: 2016/10/19
// --------------------------------------------------------------------
// Environment used
// Windows 10 Version 1607 (OS Build 14393.321)
// Visual Studio Pro 2015 Version 14.0.25425.01 Update 3
//
//Use Visual Studio for debugging:
// SETUP
// Project properties
//   Application
//     Target framework
//       .NET Framework 3.5 (newer frameworks weren't supported)
//   Debug
//     Start Action
//       Start external program
//         full path to Forge110.exe, including .exe
//           i.e. "C:\Program Files (x86)\Sony\Sound Forge Pro 11.0\Forge110.exe"
//     Start Options
//       Working directory
//         Your Visual Studio Debug folder
//           i.e. C:\Users\<username>\Music\<solutionname>\bin\Debug\
//
// Project References
//   Add References to project:
//     Forge110.Script
//       C:\Program Files (x86)\Sony\Sound Forge Pro 11.0\Forge110.Script.dll
//     EnvDTE
//       C:\Windows\assembly\GAC\EnvDTE\8.0.0.0__b03f5f7f11d50a3a\envdte.dll
// DEBUGGING
// 1. Rebuild your solution
// 2. Add breakpoints as desired
// 3. Start Debug (F5) to launch Sound Forge
// 4. Visual Studio will run to your first breakpoint
// 5. Exit Sound Forge to finish debugging
//-------------------------------------------------------------

#endregion

/// <summary>
/// Entry Point for Sound Forge
/// In order for Forge to run the C# DLL, the class EntryPoint MUST exist outside of the namespace
/// </summary>

public class EntryPoint
{

    #region fieldDeclarations

    public static IScriptableApp ForgeApp;
    public const string SoundForgeProcessName = "Forge110";
    public const string VisualStudio2015ProgId = "VisualStudio.DTE.14.0";

    #endregion

    public string Begin(IScriptableApp app)
    {

        #region HackToDebugSoundForgeInVisualStudio

        // Get Visual Studio instance.
        object dt = Marshal.GetActiveObject(VisualStudio2015ProgId);
        DTE dte = (DTE) dt;

        // Detach debugger from Visual Studio instance.
        dte.Debugger.DetachAll();

        // Wait for process to detach.
        System.Threading.Thread.Sleep(1000);

        // Get SoundForge process ID.
        Process[] processes = Process.GetProcesses();
        int? soundForgeProcessId = null;
        foreach (Process process in processes)
        {
            if (!process.ProcessName.Equals(SoundForgeProcessName))
                continue;

            soundForgeProcessId = process.Id;
        }

        // Get SoundForge process.
        EnvDTE.Process forgeProcess = null;
        if (soundForgeProcessId != null)
        {
            forgeProcess = GetProcess((int) soundForgeProcessId);
        }

        // Visual Studio attach to SoundForge process.
        forgeProcess?.Attach();

        #endregion

        // Set a breakpoint on the line below and run in debug.
        Print("hello world");

        return null;
    }

    #region HackToDebugSoundForgeInVisualStudioMethods

    private static EnvDTE.Process GetProcess(int processID)
    {
        DTE dte = (DTE) Marshal.GetActiveObject(VisualStudio2015ProgId);
        IEnumerable<EnvDTE.Process> processes = dte.Debugger.LocalProcesses.OfType<EnvDTE.Process>();
        return processes.SingleOrDefault(x => x.ProcessID == processID);
    }

    #endregion

    public static void Print(string output)
    {
        ForgeApp.OutputText(output);
    }

    public void FromSoundForge(IScriptableApp app)
    {
        ForgeApp = app;

        app.SetStatusText(string.Format("Script '{0}' is running.", Script.Name));

        string msg = Begin(app);

        app.SetStatusText(msg != null ? msg : string.Format("Script '{0}' is done.", Script.Name));
    }
}

Comments

No comments yet - be the first to write a comment...