即时查看程序输出的VS插件

本文介绍了一款针对Visual Studio 2008的插件,该插件能够在后台自动编译并显示代码运行结果,方便开发者进行代码演示。插件通过多线程技术实现实时编译和输出,避免了频繁切换窗口带来的困扰。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 假设你正在会议室里演示即时编译的程序。有什么最佳的方式来进行演示呢?
你还在往代码窗口里输入代码?这样,你得依赖听众的想像力 ―― 他们在脑海中构造这个程序是怎样运行的。此外,你还得依赖他们相信你的代码真的像和你所说的一样运作。
      或者你要不停的运行你的代码,这样程序的输出窗口会弹出,然后听众可以看到代码的实际工作情况?这是有风险的,因为每次切换代码和输出窗口会中断流程。并且你得依赖听众会记得他们每次看到的输出信息所对应的代码。
我想这是一个可以被技术所解决的问题!我为Visual Studio 2008 写了一个小插件。它关注的是当前文本缓冲中所包含的代码,并在后台编译它,然后在前端窗口中显示输出。这一系列动作大概每2秒钟重复一次。你甚至不需要保存再重新编译代码就能看到输出 了。这个插件特意制做成独立的控制台程序因为它用不着输入。这是一幅截图:
 源代码很小而且简单易懂,并且可以从上面的链接中获得。
 
      有两个关键的地方。第一是要使用多线程进行处理。我想让源代码在后台线程中编译因此它并不会影响Visual Studio UI. 但是要获取当前缓冲的文本你必须使用UI线程,而且要显示输出你也得使用它。我使用System.Timers.Timer在后台线程触发它的事件,同时为需要UI线程的任务调用form.Invoke(…)。
      我还使用了“non-AutoReset”计时器。我让它获取源码并进行编译+运行+显示,暂停2秒后,再去获取源码并进行编译+运行+显示,如此循环。换句话说,计时器的时间间隔必须设为2 秒在处理完先前的定时事件之后。
''' <summary>
''' OnTimer 处理 non- autoreset 计时器信号。 它运行在后台线程中。从当前的缓冲区中获取
''' 源代码并编译它,然后显示输出。
''' </summary>
''' <remarks></remarks>
Sub OnTimer() Handles t.Elapsed
    Try
        Dim oldsrc = src
                ' 我们在后台线程中。 但只能从 UI 线程获取源 ...
        ' 此委托将获取源代码并将它存储在 "src" 字段中
        f.Invoke(New Action(AddressOf GetSource))
        If src <> oldsrc Then
            Dim oldoutput = output
            ' 在后台编译并运行
            output = CompileAndRun(src)
            If output <> "" OrElse oldoutput = "" Then
                ' 在屏幕上显示输出必须在 UI 线程中完成
                ' 此委托从 "output" 字段中得到要输出的内容并显示它
                f.Invoke(New Action(AddressOf ShowOutput))
            End If
        End If
    Finally
        t.Start()
    End Try
End Sub
     
       另一个关键时刻与如何运行代码并捕获它的输出有关。在“My”命名空间中,VB在这方面有很多有用的函数。我的主要问题是合理的处理异常不留任何遗漏。(注意:获取临时文件名的代码并不完全准确:事实上你在某个状态之前得到一个未使用的临时文件名并不意味着这个文件名会一直不被使用;同样,它也并不意味着添加了“.vb”扩展名的临时文件名会一直不被使用。但是把这种情况处理的更准确看直来并不十分划算;不管怎样,在异常处理中我们将所有的问题恢复到正常状态。)
Function CompileAndRun(ByVal src As String) As String
    Dim fn_exe = ""
    Dim fn_src = ""
    Dim vbc As System.Diagnostics.Process = Nothing
    Dim exe As System.Diagnostics.Process = Nothing
    Try
        ' 准备编译
        fn_src = My.Computer.FileSystem.GetTempFileName() & ".vb"
        My.Computer.FileSystem.WriteAllText(fn_src, src, False)
        fn_exe = My.Computer.FileSystem.GetTempFileName() & ".exe"
        Dim framework = Environment.ExpandEnvironmentVariables("%windir%\Microsoft.Net\Framework")
        Dim latest_framework = (From d In My.Computer.FileSystem.GetDirectories(framework) Where d Like "*\v*" Select d).Last
 
        ' 编译
        vbc = System.Diagnostics.Process.Start(New ProcessStartInfo _
                            With {.CreateNoWindow = True, _
                                  .UseShellExecute = False, _
                                  .FileName = latest_framework & "\vbc.exe", _
                                  .Arguments = String.Format("/out:""{0}"" /target:exe ""{1}""", fn_exe, fn_src)})
        Dim vbc_done = vbc.WaitForExit(3000)
        If Not vbc_done Then Return ""
        If vbc.ExitCode <> 0 Then Return ""
 
        ' 运行
        Dim pinfo = New ProcessStartInfo With {.CreateNoWindow = True, _
                                               .UseShellExecute = False, _
                                               .FileName = fn_exe, _
                                               .RedirectStandardOutput = True}
        exe = New System.Diagnostics.Process With {.StartInfo = pinfo}
        exe.Start()
        Dim output = exe.StandardOutput.ReadToEnd
        Dim exe_done = exe.WaitForExit(3000)
        If Not exe_done Then Return ""
        Return output
    Finally
        ' 我们可以巧妙的关闭 VBC 进程
        If vbc IsNot Nothing Then
            If Not vbc.HasExited Then
                Try : vbc.Kill() : Catch ex As Exception : End Try
                Try : vbc.WaitForExit() : Catch ex As Exception : End Try
            End If
            Try : vbc.Close() : Catch ex As Exception : End Try
            vbc = Nothing
        End If
 
        ' 我们可以巧妙的关闭 EXE
        If exe IsNot Nothing Then
            If Not exe.HasExited Then
                Try : exe.Kill() : Catch ex As Exception : End Try
                Try : exe.WaitForExit() : Catch ex As Exception : End Try
            End If
            Try : exe.Close() : Catch ex As Exception : End Try
            exe = Nothing
        End If
 
        ' 删除剩余的文件
        Try : My.Computer.FileSystem.DeleteFile(fn_exe) : Catch ex As Exception : End Try
        Try : My.Computer.FileSystem.DeleteFile(fn_src) : Catch ex As Exception : End Try
    End Try
End Function
 

转载于:https://www.cnblogs.com/coderdream/archive/2008/12/31/1365734.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值